mnist classification

heyme·2022년 3월 14일
0

review

목록 보기
1/2

오늘은 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

data preprocessing

사용하는 데이터는 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)

model define

이제 모델을 정할 차례이다. sequential 모델을 사용하고 먼저 flatten으로 펴서
바로 dense를 2번 거친다. 이때, 사용하는 활성함수는 각각 relu와 softmax이다.
결과적으로 10개의 class 중 예측한 분류 결과를 얻을 수 있다.

  • Flatten은 2차원 data를 flatten하며 한 줄로 펴는 역할을 한다.
  • Dense layer는 fc 라고도 하며 완전 연결 계층에서 이뤄진 연산 정보를 다음 layer로 전달한다. 연산이 끝난 뒤 사용되는 활성함수도 지정해야 하는데, 관련 내용은 따로
    정리해 두었다. --> https://velog.io/@heyme/activation-function-fh30vns5
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

이렇게 생성된 모델을 출력하면 다음과 같다.

model training

모델을 만들었으니 학습을 해야 하는데, 그 전에
loss function, optimizer, metric를 정해야 한다.

model.compile(loss='categorical_crossentropy', 
              optimizer='adam', 
              metrics=['accuracy'])
  • loss function은 손실함수로, 보통 회귀에서 MSE, 분류에서 crossentropy를 사용한다.
    --> https://velog.io/@heyme/loss-function
  • optimizer는 모델 가중치를 업데이트하는 방법으로, loss를 최소화하는 방향을 찾는 길이라고 이해하면 쉽겠다. --> https://velog.io/@heyme/optimize
  • metrics : 평가기준으로 훈련, 테스트 단계에 이를 기준으로 판단한다.

여기에서는 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()

model predict

이제 학습된 모델로 예측을 해보려고 한다.

# 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'가 가장 큰 확률이므로 그 예측이 맞음을 알 수 있다.

0개의 댓글