Convolution을 사용하여 Fashion MNIST를 개선하는 방법을 프로그래밍한다. 모델에 단일 컨볼루션 레이어와 단일 MaxPooling 2D 레이어만 추가하여 MNIST 정확도를 99.5% 이상으로 향상할 수 있는지 확인한다.
정확도가 이 값을 초과하면 훈련을 중단한다. 이는 10 epoch 이내에 발생해야 하므로 훈련을 위한 epoch 수를 하드 코딩하는 것은 괜찮지만 위의 측정항목에 도달하면 훈련이 종료되도록 하는 콜백을 디자인한다.
99.5% 정확도에 도달하면 "99.5% 정확도에 도달했으므로 훈련 취소!"라는 문자열을 인쇄한다.
**[1] 필요한 라이브러리 import
import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
[2] Load the data
data_path = os.path.join(current_dir, "data/mnist.npz")
(training_images, training_labels), _ = tf.keras.datasets.mnist.load_data(path=data_path)
[3] Pre-processing the data
이미지 데이터를 처리할 때 중요한 단계 중 하나는 데이터를 전처리하는 것이다.
전처리 단계에서 컨벌루션 신경망에 입력될 데이터세트에 변환을 적용할 수 있다.
여기서는 데이터에 두 가지 변환을 적용한다.
한 가지 변환은 추가 차원을 갖도록 데이터의 모양을 변경한다.
그 이유는 일반적으로 이미지 데이터를 표현하기 위해 (배치 차원을 계산하지 않고) 3차원 배열을 사용하기 때문이다.
세 번째 차원은 RGB 값을 사용하여 색상을 나타낸다. 이 데이터는 흑백 형식일 수 있으므로 3차원은 실제로 분류 프로세스에 대한 추가 정보를 추가하지 않지만 상관없이 좋은 방법이다.
또 다른 하나는 0과 1 사이의 값이 되도록 픽셀 값을 정규화한다.
배열의 모든 값을 최대값으로 나누어 이를 달성할 수 있다.
이러한 텐서는 numpy.ndarray 유형이므로 reshape 또는 Divide와 같은 함수를 사용하여 아래 reshape_and_normalize 함수를 완성할 수 있다.
def reshape_and_normalize(images):
images = images.reshape(-1,28,28,1)
images = images/ 255.0
return images
(training_images, _), _ = tf.keras.datasets.mnist.load_data(path=data_path)
training_images = reshape_and_normalize(training_images)
print(f"Maximum pixel value after normalization: {np.max(training_images)}\n")
print(f"Shape of training set after reshaping: {training_images.shape}\n")
print(f"Shape of one image after reshaping: {training_images[0].shape}")
# output
Maximum pixel value after normalization: 1.0
Shape of training set after reshaping: (60000, 28, 28, 1)
Shape of one image after reshaping: (28, 28, 1)
[4] Defining callback
이제 99.5%의 정확도에 도달한 후 훈련이 중지되도록 하는 콜백을 디자인한다.
측정항목 정확도를 확인하는 방식으로 콜백을 정의한다.
(acc는 일반적으로 사용할 수도 있지만 채점 오류가 발생하지 않도록 전체 단어를 사용하여 정의하기 위해 채점자는 이 측정항목을 정확도라고 부른다)
class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if logs.get('accuracy') is not None and logs.get('accuracy') > 0.995:
print("\nReached 99.9% accuracy so cancelling training!")
self.model.stop_training = True
[5] Convolutional Model
마지막으로 아래 convolutional_model 함수를 완성한다.
이 함수는 컨벌루션 신경망을 반환해야 한다.
모델이 10개의 에포크 이전에 99.5% 이상의 정확도를 달성해야 하도록 모델을 설계한다.
네트워크 아키텍처는 무엇이든 시도해 볼 수 있지만 해당 데이터에는 복잡한 아키텍처가 필요하지 않. 예를 들어 컨볼루셔널 레이어는 하나만 필요하다.
시간 초과 문제를 방지하려면 컨벌루션 레이어와 밀집 레이어의 단위 수를 제한한다. 모델이 너무 크면 예외가 발생할 수 있다.
def convolutional_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28,28,1)),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(units=512, activation='relu'),
tf.keras.layers.Dense(units=10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
model = convolutional_model()
model_params = model.count_params()
assert model_params < 1000000, (
f'Your model has {model_params:,} params. For successful grading, please keep it '
f'under 1,000,000 by reducing the number of units in your Conv2D and/or Dense layers.'
)
callbacks = myCallback()
history = model.fit(training_images, training_labels, epochs=10, callbacks=[callbacks])
콜백에 정의한 메시지가 10 epoch 미만 후에 인쇄되는 경우 콜백이 예상대로 작동했다는 의미이다.
print(f"Your model was trained for {len(history.epoch)} epochs")
# output
# Your model was trained for 5 epochs
콜백이 훈련을 중지하지 않은 경우 정확성(예: acc) 이외의 측정항목을 사용하여 모델을 컴파일했기 때문일 수 있다. 측정항목을 정확하게 설정했는지 확인한다. 다음 셀을 실행하여 확인할 수 있다.
if not "accuracy" in history.model.metrics_names:
print("Use 'accuracy' as metric when compiling your model.")
else:
print("The metric was correctly defined.")
# output
The metric was correctly defined.
여기서 좋은 모델 스트럭처 중 하나는 아래의 코드를 참고하면 좋다.
- A Conv2D layer with 32 filters, a kernel_size of 3x3, ReLU activation function and an input shape that matches that of every image in the training set
- A MaxPooling2D layer with a pool_size of 2x2
- A Flatten layer with no arguments
- A Dense layer with 128 units and ReLU activation function
- A Dense layer with 10 units and softmax activation function
def convolutional_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(units=128, activation='relu'),
tf.keras.layers.Dense(units=10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model