AI/TensorFlow & PyTorch

[TensorFlow] 텐서플로우(TensorFlow 2.x) Fashion MNIST

byunghyun23 2021. 3. 5. 19:12

본 포스팅은 다항 분류의 예제입니다.

MNIST(Mixed National Institute of Standards and Technology database)는 손으로 쓴 숫자 글씨를 모아놓은 데이터세트 입니다.

Fashion MNIST는 손글씨가 아니라 옷, 신발, 가방 등의 이미지를 모아놓은 데이터세트 입니다.

그레이스케일 이미지이고 범주의 수가 10개, 각 이미지의 크기가 28x28 픽셀이라는 점은 MNIST와 동일합니다.

Fig 1. Category of Fashion MNIST

Fashion MNIST 데이터를 이용하여 모델을 학습하고, 이미지를 분류 해보겠습니다.

코드는 아래와 같습니다.

import matplotlib.pyplot as plt
import tensorflow as tf

# 5.19 Fashion MNIST 데이터셋 불러오기
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_X, train_Y), (test_X, test_Y) = fashion_mnist.load_data()
print(type(train_X))

print(len(train_X), len(test_X))

# 5.20 데이터 확인
plt.imshow(train_X[0], cmap='gray')
plt.colorbar()
plt.show()

print(train_Y[0])

# 5.21 데이터 정규화
train_X = train_X / 255.0
test_X = test_X / 255.0

print(train_X[0])

# 5.22 Fashion MNIST 분류 모델
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28,28)),
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dense(units=10, activation='softmax')
])

model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.summary()

# 5.23 Fashion MNIST 분류 모델 학습
history = model.fit(train_X, train_Y, epochs=25, validation_split=0.25)

# 5.24 Fashion MNIST 분류 모델 학습 결과 시각화
plt.figure(figsize=(12, 4))

plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], 'b-', label='loss')
plt.plot(history.history['val_loss'], 'r--', label='val_loss')
plt.xlabel('Epoch')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], 'g-', label='accuracy')
plt.plot(history.history['val_accuracy'], 'k--', label='val_accuracy')
plt.xlabel('Epoch')
plt.ylim(0.7, 1)
plt.legend()

plt.show()

# 5.25 Fashion MNIST 분류 모델 평가
model.evaluate(test_X, test_Y)

코드를 분석해보면,

먼저 keras를 이용하여 fashion_mnist 데이터를 가져옵니다.

수집한 데이터는 반드시 확인해봐야 합니다.

print(train_Y[0])의 값은 9으로, 해당하는 범주는 부츠(boots)입니다.

Fig 1. fashin mnist[0] data

 

이미지 픽셀값을 255로 나누면 0.0~0.1 사이의 값으로 정규화 할 수 있습니다.

train_X = train_X / 255.0
test_X = test_X / 255.0

 

이전에 실습했던 다항 분류와 달리 위 코드에는 to_categorical() 함수를 사용하고 있지 않습니다.

fashin_mnist에서 정답 행렬을 원-핫 인코딩으로 변경할 경우, 필요한 정보는 정답 레벨 숫자 하나뿐인데

그것을 표현하기 위해 10개의 숫자를 사용해야 합니다. 이렇게 대부분의 값이 0인 행렬을 희소 행렬(sparse_matrix) 이라고 합니다.

( print(train_Y[0])를 표현하기 위해 [0, 0, 0, 0, 0, 0, 0, 0, 1]를 사용)

이것은 매우 비효율적이기 때문에 [0, 0, 0, 0, 0, 0, 0, 0, 1] 대신 9로 표현할 수 있습니다.

그 방법은 compile() 함수의 loss를 'sparse_categorical_crossentropy'로 설정하는 것입니다.

이는 별도의 데이터 전처리 없이 희소 행렬을 정답 행렬로 사용할 수 있도록 합니다.

 

현재 이미지 데이터는 2차원 배열 (28x28 픽셀)이기 때문에 학습을 위하여 Flatten()을 이용하여

1차원 배열(28*28=784)로 변환합니다. Flatten층은 학습되는 가중치는 존재하지 않고 데이터를 변환하기만 합니다.

 

compile()을 이용하여 모델 설정 후 fit()으로 학습하고, 손실도와 정확도를 시각화합니다.

 

Fig 2. Loss and accuracy

테스트 데이터를 기반으로 evaluate()를 이용하여 모델을 평가합니다.

Fig 3. Model evaluation

정확도는 약 88%밖에 되지 않습니다.

네트워크 구조 (뉴런, 계층 수, 학습률, 배치 크기) 또는 학습 기법을 변경하여 정확도를 더 올릴 수 있습니다.

관련 내용은 '합성곱 신경망(CNN)' 확인할 수 있습니다.