티스토리 뷰

패션 MNIST 데이터셋을 활용해 각 의류들이 해당하는 의류의 종류를 밝혀내보자!

 

가상환경에서 tensorflow, jupyter notebook, matplotlib, numpy를 설치후 jupyter notebook을 열어서 코드를 돌려보며 이해해보자.

 

1. 사용할 모듈을 import 합니다.

# TensorFlow and tf.keras
import tensorflow as tf

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

=> 만약 설치가 제대로 되어있지 않다면 해당 모듈을 찾을 수 없다는 에러를 발견할 것임. 

이러한 에러는 본인이 jupyter notebook을 연 환경에 제대로 설치가 되어있는지 확인할 필요가 있으며 그 환경은 가상환경이 될 것임. 만약 가상환경에서 jupyter notebook을 열지 않았다거나 그 가상환경이 아닌 다른 환경에 numpy혹 tensorflow를 설치했다면 당연히 찾을 수 없다고 뜰 것임.

 

 

2. MNIST 데이터셋 불러오기

손글씨 숫자인식처럼 60,000개의 이미지를 training set으로 활용하고 이 training set을 활용해서 fit함으로써 신경망 모델을 학습시킨 가중치가 올바른지 확인하기 위해서 (즉, training set을통해 만든 예측모델이 올바른지 확인하기 위해서) 비교해볼 10,000개의 이미지를 test set으로 불러오게 되어있습니다.

fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

=> 손글씨 숫자인식처럼 load_data()함수를 활용하면 tensorflow에서 제공하는 데이터셋을 불러올 수 있습니다.

laod_data()를 통해서 4개의 Numpy 배열이 반환되며 Numpy배열을 활용하면 우리는 딥러닝에 필요한 계산들을 쉽게 할 수 있습니다. 

=> (train_images, train_labels)의 경우

60,000개의 이미지 데이터들이 생성. label에는 데이터의 실제 분류값이 들어가있으며(0-9사이의 정수 배열) images에는 28*28사이즈를 가지며 각 픽셀은 0-255사이의 값을 갖습니다.

=>(test_images, test_labels)의 경우

10,000개의 이미지 데이터들이 생성. 이하 trianing set과 같습니다. 다른점이 있다면 사용되는 목적이라는 것입니다.

 

* y_label이 0-9사이의 정수배열을 가지는 이유[why?]

우리는 class가 총 10개로된 의류를 분류를 할것이기에 Numpy 배열 0-9까지 10의 size를 가지는 것을 만들 수 있습니다. 이때 0은 T-shirt/top 1은 Trouser class를 의미하고 ~~~ 9는 Ankle boot를 의미합니다.

각 배열마다 특정한 숫자를 가지게 결과가 나올것이고 이때 숫자가 가장 큰 값이 정답 클래스 즉 정답 옷 종류가 되겠습니다.

 

3. 데이터 전처리

이미지 데이터의 픽셀값이 각각 0-255사이의 값을 가지기에 255로 training set와 test set을 모두 255로 나눠서 적용시킵니다.

train_images = train_images / 255.0

test_images = test_images / 255.0

4. 신경망 모델 만들기 : 모델구성단계 (setting)

tf.keras.layers.Dense : 신경망 모델 구성을 위한 Dense 층 들의 가중치를 훈련하는 학습을 진행할 수 있음.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10)
])

=> tf.keras.layers.Flatten : 이미지가 픽셀 28*28크기의 사이즈를 가지고 있기 때문에 평탄화시키는 작업이 필요한데 총 784 픽셀을 가진 1차원 배열로 반환하는 역할을 해줍니다.

 

[왜 1차원 배열화 시키는지? 벡터화시키는 이유는? why?]

그것은 신경망이 모두 1차원으로 구성되어있기때문에 연산을 위해서 당연히 입력 이미지도 역시 1차원 배열화 시켜줘야합니다. 신경망 곱의 연산을 통해서 이해할 수 있습니다.

 

=> tf.keras.layers.Dense : 신경망 층을 나타내주는 코드로 첫번째로 작성된 Dense의 경우 노드수가 128개 그리고 활성화함수는 relu함수를 가져서 y값을 반환하고 이 값은 다시 두번재 Dense로 들어가 10개의 노드를 만나서 softmax 층으로 확률값으로 y값을 반환한다. 결국 마지막 확률값이 반환되면 그중 가장 큰 값이 존재할테고 그 값이 존재하는 해당 번호(0-9까지)에 해당하는 의상이 예측된 의류이다.

 

5. 모델 컴파일 : 모델세팅단계2

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

SparseCategoricalCrossentropy를 손실함수로 사용하여 그 손실값을 최소로 하게끔하며 compile할 것이며 metircs에는정확도를 담으며 훈련 및 테스트 단계를 계속 모니터링합니다. 또한 옵티마이저는 adam으로 손실함수를 기반으로 모델이 업데이트 되는 방법을 선택합니다. 

즉, 손실함수를 SparseCategoricalCrossentropy으로 하고 이를 통해 나온 예측값과 실제값의 차이 그 손실값을 adam기반으로 모델이 업데이트되며 더 나은 신경망을 구성할 것이며 이를 통해 나오는 정확도가 메트릭으로 들어간다는 것입니다.

 

 

6. 모델 훈련

model.fit(train_images, train_labels, epochs=10)

위에서 설정한 model을 tensorflow에서 제공하는 fit을활용해서 compile설정 모델설정한것들을 기반으로 하여 훈련시켜줍니다.

epochs가 10번이라는 것은 전체 10번 모든 과정을 반복한다는 것을 의미합니다.

 

Epoch 1/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.4989 - accuracy: 0.8247 Epoch 2/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.3724 - accuracy: 0.8668 Epoch 3/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.3333 - accuracy: 0.8786 Epoch 4/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.3104 - accuracy: 0.8855 Epoch 5/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2919 - accuracy: 0.8911 Epoch 6/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2779 - accuracy: 0.8978 Epoch 7/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2646 - accuracy: 0.9011 Epoch 8/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2561 - accuracy: 0.9042 Epoch 9/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2454 - accuracy: 0.9092 Epoch 10/10 1875/1875 [==============================] - 3s 1ms/step - loss: 0.2388 - accuracy: 0.9108 <keras.callbacks.History at 0x7f1d1670c150>

 

test셋을 이 훈련모델에 적용시켜보자

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)

이때 정확도는 0.8830000162124634 으로 나오게 되는데 이것은 training set에서의 정확도보다 낮게 나온것으로 보아 training set에서 과적합 문제가 발생했다는 것을 알 수 있다.

 

7. 모델을 활용한 예측

우선 예측모델을 설정해주는데 아래와 같고

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])

훈련시킨 model을 가지고 예측하기 위해 세팅하며 모델로 소프트맥스로 확률값을 반환하도록 설정합니다.

predictions = probability_model.predict(test_images)

설정한 예측모델을 predict를 활용해서 모델의 예측값을 받아올 수 있습니다.

 

8. 훈련된 모델을 사용하여 특정 이미지에 대한 예측을 만들자.

 

 

img = test_images[1]

img = (np.expand_dims(img,0))
# 2차원 배열로 만들어서 사용을 해야하기에 이차원 배열로 만들어줍니다.

predictions_single = probability_model.predict(img)
#img를 예측모델에 predict를활용해 예측하고 그 결과를 single예측값으로 받아옵니다.

print(predictions_single)

[[3.6173755e-05 3.2209617e-14 9.9866760e-01 1.6559891e-11 1.0769934e-03 1.6140698e-13 2.1918291e-04 3.4505306e-21 3.6745976e-10 1.0840150e-14]]

이것이 0-9 index번호를 가지는 확률값들이고 가장 큰 값이 2번입니다.

=> 따라서 2번 모델을 최종 결과로 가지는 Pullover의류로 분류해냅니다.

np.argmax(predictions_single[0])

결과 : 2