오늘은 github에 올린 digit classification을 코드 하나하나 보려고 한다. 딥러닝 분류 문제에서 mnist dataset을 이용하는 classification은 매우 쉽고 간단한 문제이지만, 기본적인만큼 자세히 아는 것이 중요하다고 생각하여 review 해보겠다.
먼저, 필요한 패키지를 불러온다.
from tensorflow.keras.datasets import mnist # mnist dataset 사용
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.utils import to_categorical
import matplotlib.pyplot as plt
사용하는 데이터는 keras의 mnist dataset을 가져온다.
mnist : 0~9까지의 손글씨 흑백 데이터로 28x28 크기를 갖는다.
(x_train, y_train), (x_test, y_test) = mnist.load_data()
train data 60000장, test data 10000장으로 이뤄져 있고
해당 data shape과 이미지는 아래와 같이 확인 가능하다.
print(x_train.shape) # (60000, 28, 28)
print(x_test.shape) # (10000, 28, 28)
print(y_train.shape) # (60000,)
print(y_test.shape) # (10000,)
plt.figure(figsize=(3,3))
plt.imshow(x_train[0])
print(y_train[0])
0~255 사이의 픽셀값을 0~1 사이로 scaling 한다. feature의 값이 훨씬 크면,
학습시 다른 요소들보다 상대적으로 그 영향이 커지는 것을 막기 위해 사용한다.
x_train = x_train / 255.0
x_test = x_test / 255.0
0~9 까지 class의 개수를 선언하고 그 class의 개수대로
to_categorical 함수를 사용하여 one hot encoding 한다.
num_classes = 10
y_train = to_categorical(y_train, num_classes)
y_test = to_categorical(y_test, num_classes)
print(y_train[0]) # 5
print(y_train.shape) # (60000, 10)
print(y_test.shape) # (10000, 10)
이제 모델을 정할 차례이다. sequential 모델을 사용하고 먼저 flatten으로 펴서
바로 dense를 2번 거친다. 이때, 사용하는 활성함수는 각각 relu와 softmax이다.
결과적으로 10개의 class 중 예측한 분류 결과를 얻을 수 있다.
model = Sequential()
model.add(Flatten(input_shape = (28, 28))) # in: (28, 28), out: 784
model.add(Dense(128, activation='relu')) # in: 784, out: 128
model.add(Dense(num_classes, activation='softmax')) # in: 128, out: 10
이렇게 생성된 모델을 출력하면 다음과 같다.
모델을 만들었으니 학습을 해야 하는데, 그 전에
loss function, optimizer, metric를 정해야 한다.
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
여기에서는 loss로 crossentropy, optimizer로 adam을 사용하였다.
이제 진짜 학습을 위해 epoch과 batch size를 정하고 train 시켜보자
history = model.fit(x_train,
y_train,
batch_size=128,
epochs=5,
verbose=1,
validation_data=(x_test, y_test))
여기서 batch_size는 한번에 학습할 데이터 수이다. 사이즈가 클수록 그 속도는 빨라지지만 메모리를 많이 쓰게되고, 작을수록 속도는 느리지만 대신 차지하는 메모리가 많아진다. epochs은 전체 데이터를 몇 번 반복하여 학습할지 나타낸다.
아래는 5번 돌렸을 때, 학습 결과이다.
다음은 epoch에 따른 위의 학습 결과를 시각화 한 것이다.
학습할수록 정확도는 증가가고 loss는 감소함을 알 수 있다.
train과 test의 차이는 답을 아는지 모르는지의 차이가 된다.
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(['train', 'test'], loc='lower right')
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'test'], loc='lower right')
plt.show()
이제 학습된 모델로 예측을 해보려고 한다.
# 3가지 test 데이터로 모델 예측
test_image = x_test[:3]
pred_number = model.predict(test_image)
for i, img in enumerate(test_image):
plt.figure(figsize=(3,3))
plt.imshow(img)
plt.show()
print(pred_number[i])
print("Prediction : Number is", pred_number[i].argmax())
결과를 보면 합이 1이 되는, 0부터 9까지의 확률을 볼 수 있다.
그중에 '2'가 가장 큰 확률이므로 그 예측이 맞음을 알 수 있다.