๋ณธ ํฌ์ŠคํŠธ๋Š” ํŒจ์ŠคํŠธ์บ ํผ์Šค ํŒŒ์ด์ฌ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๋”ฅ๋Ÿฌ๋‹ ์˜์ƒ์ธ์‹ ๋ฐ”์ด๋ธ” ๊ฐ•์˜๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

 

์˜ฌํ•ด ์ƒ๋ฐ˜๊ธฐ๊ฐ€ ์ง€๋‚˜๊ฐ€๊ธฐ ์ „ ๋”ฅ๋Ÿฌ๋‹ ๊ณต๋ถ€๋ฅผ ๊นŠ๊ฒŒ ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋‹ค. CNN, RNN, LSTM ๋“ฑ์˜ ์ด๋ก ์€ ํ•™๋ถ€์ƒํ™œ์„ ํ•˜๋ฉด์„œ ๊ฝค๋‚˜ ์ตํ˜”๋Š”๋ฐ, ๋”ฅ๋Ÿฌ๋‹ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ๋งํ•˜๋Š” ๊ฒƒ์€ ํ•ด๋ณด์ง€ ์•Š์•˜๊ธฐ์—, ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•œ ๊ฐ€์ง€ ์ •๋„๋Š” ๋Šฅ์ˆ™ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ์‚ผ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ฐ•์˜๋ฅผ ๋”ฐ๋ผ keras๋ฅผ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ธ๋ฐ, 

keras ๋ฌธ์„œ ๋ฅผ ๋“ค์–ด๊ฐ€ ์‚ฌ์šฉ๋ฒ•์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ๊ธฐ๋ณธ์ ์ธ ๋ชจ๋ธ๋ง์€ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ๋ฐฐ์šธ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. 

 

 

 


1. ํ•„์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import 

# TensorFlow and tf.keras
import tensorflow as tf 
from tensorflow import keras 
#  Helper libraries 
import numpy as np 
import matplotlib.pyplot as plt 
import math

print(tf.__version__) # tensorflow ๋ฒ„์ „ ํ™•์ธ

tensorflow, keras๋ฅผ import ํ•ด์ค€๋‹ค.  ํ•„์ž๋Š” google colab ์—์„œ ์‹ค์Šต์„ ์ง„ํ–‰ํ•˜์˜€๊ณ , ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์„ ๊ธฐ์ค€์œผ๋กœ tf ๋ฒ„์ „ 2.8.0 ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ๋ฐ–์— ํ•„์š”ํ•œ numpy, matplotlib, math๋ฅผ import ํ•ด ์ค€๋‹ค. 

 

 


2. batch size, epochs, num_classes ์ •์˜

# Define Constants 
batch_size = 128 
epochs = 100 
num_classes = 10

batch_size: ๋ฐ์ดํ„ฐ๋ฅผ ๋ช‡๊ฐœ์”ฉ ๋ฌถ์–ด์„œ ํ•™์Šตํ•  ๊ฒƒ์ธ๊ฐ€? -> 128๊ฐœ์”ฉ ๋ฌถ์–ด์„œ ํ•™์Šตํ•˜๊ฒ ๋‹ค

ephocs: ํ•™์Šต์„ ๋ฐ˜๋ณตํ•˜๋Š” ํšŸ์ˆ˜ -> 100๋ฒˆ ํ•™์Šตํ•˜๊ฒ ๋‹ค

num_classes: ํด๋ž˜์Šค์˜ ๊ฐœ์ˆ˜ -> MNIST๋Š” 0~9๊นŒ์ง€ 10๊ฐœ์ด๋ฏ€๋กœ 10

 

 

  • 60000์žฅ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ํ•™์Šตํ•˜์ง€ ์•Š๊ณ  batch size๋ฅผ ์„ค์ •ํ•˜๋Š” ์ด์œ 

๋ฐฐ์น˜๋ฅผ ๋‚˜๋ˆ ์„œ ํ•™์Šตํ•˜๊ฒŒ๋˜๋ฉด ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์ŠคํŠธ๋ ˆ์ดํŠธ๋กœ ์ญ‰ ํ•™์Šต๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, batch size๋งŒํผ ํ•™์Šต๋˜๋ฉด์„œ ์˜ˆ์ธก ๊ฐ’์ด ๋งž๊ฑฐ๋‚˜ ํ‹€๋ฆฐ ๊ฒฝ์šฐ๊ฐ€ ๊ฐ ๋ฐฐ์น˜๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๊ฐ„์ค‘๊ฐ„ ๊ฐ€์ค‘์น˜๊ฐ€ ์กฐ์ ˆ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋” ์ข‹์€ ์„ฑ๋Šฅ์„ ๊ธฐ๋Œ€ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

(์‹ค์ œ๋กœ ์‹คํ—˜ํ•ด๋ณด์•˜๋”๋‹ˆ batch size๋ฅผ 60000์žฅ์œผ๋กœ ํ–ˆ์„ ๋•Œ ์ •ํ™•๋„๊ฐ€ 0.02์ •๋„ ๋‚ฎ๊ฒŒ ๋‚˜์™”๋‹ค. (MNIST ๋ฐ์ดํ„ฐ ๊ธฐ์ค€) ๊ทธ๋ฆฌ๊ณ  batch size๊ฐ€ ์ž‘์•„์งˆ ์ˆ˜๋ก ํ•™์Šต ์†๋„๊ฐ€ ๋Š๋ ค์ง„๋‹ค. ์•„์ง ๋ฐฐ์น˜์‚ฌ์ด์ฆˆ๋ฅผ ์กฐ์ •ํ•  ๋ ˆ๋ฒจ์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ฐฐ์น˜์‚ฌ์ด์ฆˆ์— ๋”ฐ๋ผ ์„ฑ๋Šฅ์ด ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ์ง์ ‘ ํ™•์ธํ•˜๋‹ˆ ์ ์ ˆํ•œ ๋ฐฐ์น˜์‚ฌ์ด์ฆˆ๋ฅผ ์„ค์ •ํ•ด์ฃผ๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ธ ๊ฒƒ ๊ฐ™์•„๋ณด์ธ๋‹ค. )

 

 

 


3. MNIST ๋ฐ์ดํ„ฐ์…‹ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

# Download MNIST dataset 
mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

์›Œ๋‚™ ์œ ๋ช…ํ•œ MNIST ๋ฐ์ดํ„ฐ์…‹์€ keras์—์„œ ์ œ๊ณตํ•ด์ฃผ๋ฏ€๋กœ ๋”ฐ๋กœ ๋‹ค์šด๋ฐ›์„ ํ•„์š” ์—†์ด ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.  

len(train_images), len(test_images)

 (60000, 10000) 

train์€ 60000์žฅ, test๋Š” 10000์žฅ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 

 

 


4. ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ ํ•™์Šต

(1) normailze (0.0 ~ 1.0 ์‚ฌ์ด์˜ ๊ฐ’์ด ๋˜๋„๋ก) 

# Normalize the input image so that each pixel value is between 0 to 1 
train_images = train_images / 255.0 
test_images = test_images / 255.0

๋ฐ์ดํ„ฐ๋ฅผ floatํ˜•์œผ๋กœ ๋งŒ๋“ค๋ฉด์„œ 0.0~1.0 ์‚ฌ์ด๋กœ ์ •๊ทœํ™”ํ•ด์ค€๋‹ค. 

 

 

(2) ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ ์ •์˜

# Define the model architecture 
model = keras.Sequential([
                          keras.layers.Flatten(input_shape=(28, 28)),
                          keras.layers.Dense(128, activation=tf.nn.relu),
                          keras.layers.Dense(num_classes, activation='softmax')
])
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

๋ชจ๋ธ์€ keras.Sequential์— ์ธต์„ ํ•˜๋‚˜ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ง๊ด€์ ์œผ๋กœ ๋ชจ๋ธ๋ง์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. flatten์œผ๋กœ ํ•œ ์žฅ๋‹น 2์ฐจ์› ๋ฐฐ์—ด 28x28์ธ ์ด๋ฏธ์ง€๋ฅผ 1์ฐจ์›์œผ๋กœ ๋งŒ๋“ค์–ด ์ค€๋‹ค. ๊ทธ๋‹ค์Œ Dense layer๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , activation ํ•จ์ˆ˜๋Š” relu๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋งˆ์ง€๋ง‰ ์ธต์—๋Š” ํด๋ž˜์Šค์˜ ๊ฐœ์ˆ˜์™€ softmax ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ํด๋ž˜์Šค ๋ณ„ ํ™•๋ฅ ๋กœ ๋‚˜์˜ค๊ฒŒ๋” ๋งŒ๋“ค์–ด์ค€๋‹ค. 

 

model.complie๋กœ optimizer์™€ lossํ•จ์ˆ˜, metrics (ํ‰๊ฐ€์ง€ํ‘œ)๋ฅผ ์„ค์ •ํ•ด ์ค€๋‹ค. 

 

์ด์ œ ๋ชจ๋ธ ํ•™์Šตํ•  ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ค. 

 

 

(3) ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ ํ•™์Šต

history = model.fit(train_images, train_labels, epochs=epochs, batch_size=batch_size)

train ๋ฐ์ดํ„ฐ์…‹๊ณผ ์•ž์„œ ์ง€์ •ํ–ˆ๋˜ ephocs, batch_size๋ฅผ ์„ค์ •ํ•ด ์ค€๋‹ค. 

 


5. ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ ํ‰๊ฐ€

(1) loss, accuracy ํ™•์ธ

test_loss, test_acc = model.evaluate(test_images, test_labels)
print("Test Loss: ", test_loss)
print("Test Accuracy: ", test_acc)

 Test Loss: 0.12909765541553497 

 Test Accuracy: 0.98089998960495 

์•„์ฃผ ๊ธฐ๋ณธ์ ์ธ ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์˜€์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  0.98์ด๋ผ๋Š” ๋†’์€ ์ •ํ™•๋„๊ฐ€ ๋‚˜์™”๋‹ค. ๋ชจ๋“  ํ•™์Šต ๊ฒฐ๊ณผ๊ฐ€ ์ด๋žฌ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค. 

 

 

 

(2) ํ•„์š” ํ•จ์ˆ˜ ์ •์˜ 

# 1. ์›ํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜ 
def show_sample(images, labels, sample_count=25):
  # Create a square with can fit {sample_count} images
  grid_count = math.ceil(math.ceil(math.sqrt(sample_count)))
  grid_count = min(grid_count, len(images), len(labels))

  plt.figure(figsize=(2*grid_count, 2*grid_count))
  for i in range(sample_count):
    plt.subplot(grid_count, grid_count, i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(images[i], cmap=plt.cm.gray)
    plt.xlabel(labels[i])
  plt.show()

###################################################################
# 2. ํŠน์ • ์ˆซ์ž์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜ 
# Helper function to display specific digit images 
def show_sample_digit(images, labels, digit, sample_count=25):
  # Create a square with can fit {sample_count} images
  grid_count = math.ceil(math.ceil(math.sqrt(sample_count)))
  grid_count = min(grid_count, len(images), len(labels))

  plt.figure(figsize=(2*grid_count, 2*grid_count))
  i = 0 
  digit_count = 0 
  while digit_count < sample_count:
    i += 1 
    if digit == labels[i]: 
      plt.subplot(grid_count, grid_count, digit_count+1)
      plt.xticks([])
      plt.yticks([])
      plt.grid(False)
      plt.imshow(images[i], cmap=plt.cm.gray)
      plt.xlabel(labels[i])
      digit_count += 1 
  plt.show()


###################################################################
# 3.์ด๋ฏธ์ง€ ํ•œ๊ฐœ๋ฅผ ํฌ๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜ 
def show_digit_image(image):
  # Draw digit image 
  fig = plt.figure()
  ax = fig.add_subplot(1, 1, 1)
  # Major ticks every 20, minor ticks every 5 
  major_ticks = np.arange(0, 29, 5)
  minor_ticks = np.arange(0, 29, 1)
  ax.set_xticks(major_ticks)
  ax.set_xticks(minor_ticks, minor=True)
  ax.set_yticks(major_ticks)
  ax.set_yticks(minor_ticks, minor=True)
  # And a corresponding grid 
  ax.grid(which='both')
  # Or if you want different settings for the grids:
  ax.grid(which='minor', alpha=0.2)
  ax.grid(which='major', alpha=0.5)
  ax.imshow(image, cmap=plt.cm.binary)

  plt.show()

28x28 ๋ฐฐ์—ด์˜ ์ด๋ฏธ์ง€๋ฅผ ์‹œ๊ฐํ™”๋กœ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 

 

 

์œ„ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž ๊น ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•ด ๋ณด์ž. 

 

  • show_sample ํ•จ์ˆ˜ ์‚ฌ์šฉ (์›ํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ ์‚ฌ์ง„ ์ถœ๋ ฅ)
show_sample(train_images, ['Label: %s' % label for label in train_labels])

์ด๋ ‡๊ฒŒ ์›ํ•˜๋Š” ๊ฐœ์ˆ˜ ๋งŒํผ ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

  • show_sample_digit ํ•จ์ˆ˜ ์‚ฌ์šฉ (ํŠน์ • ์ˆซ์ž์— ๋Œ€ํ•œ ์›ํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ์˜ ์‚ฌ์ง„ ์ถœ๋ ฅ)
show_sample_digit(train_images, train_labels, 7)

ํŠน์ • ์ˆซ์ž๋ฅผ ์›ํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

(3) train ๋ฐ์ดํ„ฐ์…‹ ํ•™์Šต ์‹œ ephoch์— ๋”ฐ๋ฅธ loss์™€ accuracy ๊ฐ’ ์‹œ๊ฐํ™”

# Evaluate the model using test dataset. - Show performance 
fig, loss_ax = plt.subplots()
fig, acc_ax = plt.subplots()

loss_ax.plot(history.history['loss'], 'ro')
loss_ax.set_xlabel('ephoc')
loss_ax.set_ylabel('loss')

acc_ax.plot(history.history['accuracy'], 'bo')
acc_ax.set_xlabel('ephoc')
acc_ax.set_ylabel('accuracy')

 

 

 

 

 

(4) test data์˜ ์˜ˆ์ธก ๊ฐ’๊ณผ ์ •๋‹ต ๊ฐ’ ๋น„๊ตํ•ด๋ณด๊ธฐ

  • ์‹ค์ œ๊ฐ’: ๊ทธ๋ฆผ
  • ์˜ˆ์ธก๊ฐ’: x label
# Predict the labels of digit images in our test datasets.
predictions = model.predict(test_images)

# Then plot the first 25 test images and their predicted labels.
show_sample(test_images, ['predicted: %s' % np.argmax(result) for result in predictions])

 

 

 

(5) show_digit_image ํ•จ์ˆ˜ ์‚ฌ์šฉ

  • ํŠน์ • ์ธ๋ฑ์Šค์˜ ์‚ฌ์ง„๊ณผ ๊ทธ๋•Œ์˜ ์˜ˆ์ธก๊ฐ’์„ ๋น„๊ตํ•ด ๋ด„
Digit = 2005 #@param {type:'slider', min:1, max:10000, step:1}
selected_digit = Digit - 1 

result = predictions[selected_digit]
result_number = np.argmax(result)
print('Number is %2d' % result_number)

show_digit_image(test_images[selected_digit])

#@param์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด ์Šฌ๋ผ์ด๋”๊ฐ€ ์ƒ๊ธด๋‹ค. ๋žœ๋ค์œผ๋กœ ์Šฌ๋ผ์ด๋“œ๋ฅผ ํ•ด์„œ ์ธ๋ฑ์Šค ๊ฐ’์„ ์ง€์ •ํ•ด ์ฃผ๋ฉด,

Number is 7

์ด์™€ ๊ฐ™์ด Number is 7 ์€ ์˜ˆ์ธก ๊ฐ’, ์ด๋ฏธ์ง€๋Š” test ์ด๋ฏธ์ง€ (์ •๋‹ต ๊ฐ’)์œผ๋กœ ๋‘๊ฐœ๋ฅผ ๋น„๊ต ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•œ MNIST๋ฐ์ดํ„ฐ์…‹์€ ์•„์ฃผ ๊ฐ„๋‹จํ•œ ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ์ธ๋ฐ๋„ ์„ฑ๋Šฅ์ด ์ข‹์•˜๋‹ค. 

๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” ์ด๋ฏธ์ง€ ๋ชจ๋ธํ•™์Šต์— ์ตœ์ ํ™” ๋˜์–ด์žˆ๋Š” CNN ๋ชจ๋ธ๋ง์„ ํ•จ์œผ๋กœ์จ MNIST์˜ ์„ฑ๋Šฅ์„ ๋”์šฑ ๋†’์—ฌ๋ณด๋Š” ๊ณต๋ถ€๋ฅผ ํ•ด ๋ณผ ๊ฒƒ์ด๋‹ค. 

+ Recent posts