๋ณธ ํฌ์คํธ๋ ํจ์คํธ์บ ํผ์ค ํ์ด์ฌ ๊ธฐ์ด๋ถํฐ ์์ํ๋ ๋ฅ๋ฌ๋ ์์์ธ์ ๋ฐ์ด๋ธ ๊ฐ์๋ฅผ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
์ฌํด ์๋ฐ๊ธฐ๊ฐ ์ง๋๊ฐ๊ธฐ ์ ๋ฅ๋ฌ๋ ๊ณต๋ถ๋ฅผ ๊น๊ฒ ํด๋ณด๊ณ ์ถ์๋ค. 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์ ์ฑ๋ฅ์ ๋์ฑ ๋์ฌ๋ณด๋ ๊ณต๋ถ๋ฅผ ํด ๋ณผ ๊ฒ์ด๋ค.