Posts MNIST 데이터로 해보는 딥러닝 (Deep Learning)
Post
Cancel

MNIST 데이터로 해보는 딥러닝 (Deep Learning)

1. MNIST


1.1 MNIST Data

  • NIST는 미국 국립표준기술연구소(National Institute of Standards and Technology)의 약자입니다. 여기서 진행한 미션 중에 손글씨 데이터를 모았는데, 그중 숫자로 된 데이터를 MNIST라고 합니다.
  • 28 * 28 픽셀의 0 ~ 9 사이의 숫자 이미지와 레이블로 구성된 데이터 셋
  • 머신러닝 공부하는 사람들이 입문용으로 사용을 많이함
  • 60000개의 훈련용 셋과 10000개의 실험용 셋트로 구성되어있음
  • 데이터는 kaggle에 있습니다. https://www.kaggle.com/oddrationale/mnist-in-csv


2. 실습


2.1 Data Load

1
2
3
4
5
6
import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
1
2
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 2s 0us/step
  • MNIST 데이터는 텐서플로우에 내장되어있다.
  • 각 사진의 픽셀의 최대값이 255값이여서, 0 ~ 1 사이의 값으로 조정함 (Min Max Scaler)


2.2 One Hot Encoding

  • 라벨값이 0 ~ 9로 되어있기 떄문에 사실은 One Hot Encoding을 해야함
  • 하지만 텐서플로우의 Loss 함수를 Sparse Categorical Crossentropy로 설정하면 같은 효과가 나옴
  • 그래서 따로 One Hot Encoding은 하지 않음

2.3 모델의 구성도

  • 784 -> 1000 -> 10
  • 784는 28픽셀 * 28픽셀로 나온 숫자이다.
  • 마지막은 0 ~ 9까지의 타겟이므로 10개
  • 총 3개의 레이어를 지나고 Output이 나오는것


2.4 모델 생성

1
2
3
4
5
6
7
model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape = (28,28)),
    tf.keras.layers.Dense(1000, activation = 'relu'),
    tf.keras.layers.Dense(10, activation = 'softmax')
])

model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])
  • 활성화 함수는 relu와 sotfmax를 사용
  • 최적화는 adam, Loss는 아까 이야기했던 sparse categorical crossentropy로 하고 평가는 accuracy로 하였음


2.5 Softmax

  • Softmax 클래스 분류 문제를 풀 때 점수 벡터를 클래스 별 확률로 변환하기 위해 흔히 사용하는 함수
  • 각 점수 벡터에 지수를 취한 후, 정규화 상수로 나누어 총 합이 1이 되도록 계산됨


2.6 Model Summary

1
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 1000)              785000    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                10010     
=================================================================
Total params: 795,010
Trainable params: 795,010
Non-trainable params: 0
_________________________________________________________________
  • 모델의 구성도와 코드의 summary가 동일한지 확인해야함


2.7 Fit

1
2
3
4
5
6
7
import time

start_time = time.time()
hist = model.fit(x_train, y_train, validation_data=(x_test, y_test),
                 epochs=10, batch_size=100, verbose=1)

print(f'Fit time : {time.time() - start_time}')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Epoch 1/10
600/600 [==============================] - 2s 3ms/step - loss: 0.2232 - accuracy: 0.9343 - val_loss: 0.1175 - val_accuracy: 0.9659
Epoch 2/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0860 - accuracy: 0.9748 - val_loss: 0.0770 - val_accuracy: 0.9767
Epoch 3/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0537 - accuracy: 0.9840 - val_loss: 0.0774 - val_accuracy: 0.9752
Epoch 4/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0364 - accuracy: 0.9888 - val_loss: 0.0780 - val_accuracy: 0.9749
Epoch 5/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0268 - accuracy: 0.9916 - val_loss: 0.0666 - val_accuracy: 0.9787
Epoch 6/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0192 - accuracy: 0.9942 - val_loss: 0.0595 - val_accuracy: 0.9813
Epoch 7/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0130 - accuracy: 0.9961 - val_loss: 0.0623 - val_accuracy: 0.9810
Epoch 8/10
600/600 [==============================] - 2s 4ms/step - loss: 0.0131 - accuracy: 0.9960 - val_loss: 0.0697 - val_accuracy: 0.9797
Epoch 9/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0125 - accuracy: 0.9961 - val_loss: 0.0725 - val_accuracy: 0.9807
Epoch 10/10
600/600 [==============================] - 2s 3ms/step - loss: 0.0072 - accuracy: 0.9980 - val_loss: 0.0712 - val_accuracy: 0.9804
Fit time : 19.54804039001465
  • 총 10번의 Epochs를 하여 학습 총 20초 정도 걸림


2.8 Acc와 Loss 그리기

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt

plot_target = ['loss', 'val_loss', 'accuracy', 'val_accuracy']
plt.figure(figsize=(12, 8))

for each in plot_target:
    plt.plot(hist.history[each], label = each)
plt.legend()
plt.grid()
plt.show()

  • 과적합 등 우려되는 상황은 보이지않는다, 또한 Loss도 잘 떨어지는것으로 확인


2.9 Accuracy 확인

1
2
3
score = model.evaluate(x_test, y_test)
print('Test loss : ', score[0])
print('Test Accuracy : ', score[1])
1
2
3
313/313 [==============================] - 0s 867us/step - loss: 0.0712 - accuracy: 0.9804
Test loss :  0.07119151949882507
Test Accuracy :  0.980400025844574


2.10 예측

1
2
3
4
5
import numpy as np

predicted_result = model.predict(x_test)
predicted_labels = np.argmax(predicted_result, axis = 1)
predicted_labels[:10], y_test[:10]
1
2
(array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9]),
 array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9], dtype=uint8))
  • predicted_labels : 예측한 데이터
  • y_test : 실제 데이터


2.11 틀린 데이터만

1
2
3
4
5
6
wrong_result = []

for n in range(0, len(y_test)):
    if predicted_labels[n] != y_test[n]:
        wrong_result.append(n)
len(wrong_result)
1
196
  • 총 1만개 중 196개의 데이터가 틀렸다


2.12 그중 16개만 랜덤으로 뽑기

1
2
3
4
import random

samples = random.choices(population= wrong_result, k = 16)
samples
1
2
3
4
5
[2135,
 5450,
 ...
 6641,
 4176]

2.13 틀린 데이터 눈으로 확인

1
2
3
4
5
6
7
8
9
plt.figure(figsize=(14, 12))

for idx, n in enumerate(samples):
    plt.subplot(4, 4, idx + 1)
    plt.imshow(x_test[n].reshape(28, 28), cmap = 'Greys', interpolation='nearest')
    plt.title('Label : ' + str(y_test[n]) + ' Predict : ' + str(predicted_labels[n]))
    plt.axis('off')
    
plt.show()

  • 실제로 헷갈리는것들도 보인다. 틀릴만 한듯


3. MNIST Fashion


3.1 MINIST Fashion Data

  • 숫자로된 MNIST Data 처럼 28 * 28 크기의 패션과 관련된 10개 종류의 데이터임
  • 레이블 설명
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    0 티셔츠/탑
    1 바지
    2 풀오버(스웨터의 일종)
    3 드레스
    4 코트
    5 샌들
    6 셔츠
    7 스니커즈
    8 가방
    9 앵클 부츠 
    


3.2 Data Load

1
2
3
4
5
6
import tensorflow as tf

fashion_mnist = tf.keras.datasets.fashion_mnist

(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
X_train, X_test = X_train / 255.0, X_test / 255.0
1
2
3
4
5
6
7
8
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 7s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 3s 1us/step
  • MNIST Fashoin 데이터도 텐서플로우에 있음
  • 아까와 마찬가지로 최대 255 숫자로 되어있어서, 0과 1사이로 만들기위해 255로 나눠줌


3.3 데이터 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
import random
import matplotlib.pyplot as plt

samples = random.choices(population=range(0, len(y_train)), k = 16)
plt.figure(figsize=(14, 12))

for idx, n in enumerate(samples):
    plt.subplot(4, 4, idx+1)
    plt.imshow(X_train[n].reshape(28, 28), cmap = 'Greys', interpolation='nearest')
    plt.title('Label : ' + str(y_train[n]))
    plt.axis('off')
    
plt.show()

  • 레이블 설명
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    0 티셔츠/탑
    1 바지
    2 풀오버(스웨터의 일종)
    3 드레스
    4 코트
    5 샌들
    6 셔츠
    7 스니커즈
    8 가방
    9 앵클 부츠 
    


3.4 모델생성

1
2
3
4
5
6
7
model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape = (28,28)),
    tf.keras.layers.Dense(1000, activation = 'relu'),
    tf.keras.layers.Dense(10, activation = 'softmax')
])

model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])
  • 모델은 숫자 데이터 할떄와 동일하게 생성


3.5 Summary

1
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_1 (Flatten)          (None, 784)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 1000)              785000    
_________________________________________________________________
dense_3 (Dense)              (None, 10)                10010     
=================================================================
Total params: 795,010
Trainable params: 795,010
Non-trainable params: 0
_________________________________________________________________
  • 모델의 구성도와 Summary가 같은지 확인


3.6 Fit

1
2
3
4
5
6
7
import time

start_time = time.time()
hist = model.fit(X_train, y_train, validation_data=(X_test, y_test),
                 epochs=10, batch_size=100, verbose=1)

print(f'Fit time : {time.time() - start_time}')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Epoch 1/10
600/600 [==============================] - 2s 4ms/step - loss: 0.4895 - accuracy: 0.8250 - val_loss: 0.4100 - val_accuracy: 0.8511
Epoch 2/10
600/600 [==============================] - 2s 3ms/step - loss: 0.3605 - accuracy: 0.8694 - val_loss: 0.3727 - val_accuracy: 0.8661
Epoch 3/10
600/600 [==============================] - 2s 4ms/step - loss: 0.3231 - accuracy: 0.8814 - val_loss: 0.3826 - val_accuracy: 0.8624
Epoch 4/10
600/600 [==============================] - 2s 4ms/step - loss: 0.2975 - accuracy: 0.8909 - val_loss: 0.3437 - val_accuracy: 0.8768
Epoch 5/10
600/600 [==============================] - 3s 4ms/step - loss: 0.2801 - accuracy: 0.8961 - val_loss: 0.3506 - val_accuracy: 0.8752
Epoch 6/10
600/600 [==============================] - 3s 4ms/step - loss: 0.2614 - accuracy: 0.9025 - val_loss: 0.3309 - val_accuracy: 0.8792
Epoch 7/10
600/600 [==============================] - 3s 4ms/step - loss: 0.2497 - accuracy: 0.9069 - val_loss: 0.3354 - val_accuracy: 0.8797
Epoch 8/10
600/600 [==============================] - 3s 4ms/step - loss: 0.2399 - accuracy: 0.9107 - val_loss: 0.3210 - val_accuracy: 0.8882
Epoch 9/10
600/600 [==============================] - 3s 5ms/step - loss: 0.2282 - accuracy: 0.9144 - val_loss: 0.3279 - val_accuracy: 0.8866
Epoch 10/10
600/600 [==============================] - 3s 5ms/step - loss: 0.2183 - accuracy: 0.9180 - val_loss: 0.3274 - val_accuracy: 0.8821
Fit time : 25.219223976135254
  • 약 25초 정도 학습시간이 걸리고, Accuracy는 숫자 데이터보다 낮게 나옴


3.7 Acc와 Loss 그리기

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as plt

plot_target = ['loss', 'val_loss', 'accuracy', 'val_accuracy']
plt.figure(figsize=(12, 8))

for each in plot_target:
    plt.plot(hist.history[each], label = each)
    
plt.legend()
plt.grid()
plt.show()

  • Acc는 오르고 Loss는 떨어져서 학습이 잘 되는것처럼 보이나 Val Loss와 Loss의 차이가 점점 벌어진다.


3.8 Test Data Acc

1
2
3
score = model.evaluate(X_test, y_test)
print('Test Loss : ', score[0])
print('Test Acc : ', score[1])
1
2
3
313/313 [==============================] - 0s 876us/step - loss: 0.3274 - accuracy: 0.8821
Test Loss :  0.32741284370422363
Test Acc :  0.882099986076355
  • Test 데이터는 0.88의 Acc가 나온다


3.9 틀린 데이터 16개 불러와서 그려보기

1
2
3
4
5
import numpy as np

predicted_result = model.predict(X_test)
predicted_labels = np.argmax(predicted_result, axis = 1)
predicted_labels[:10], y_test[:10]
1
2
(array([9, 2, 1, 1, 0, 1, 4, 6, 5, 7]),
 array([9, 2, 1, 1, 6, 1, 4, 6, 5, 7], dtype=uint8))
  • 실제 Test 데이터로 예측 후 실제 정답과 비교


1
2
3
4
5
6
wrong_result = []

for n in range(0, len(y_test)):
    if predicted_labels[n] != y_test[n]:
        wrong_result.append(n)
len(wrong_result)
1
1179
  • 그중 틀린 데이터만 뽑아옴


1
2
3
4
5
6
7
8
9
10
11
12
import random

samples = random.choices(population= wrong_result, k = 16)
plt.figure(figsize=(14, 12))

for idx, n in enumerate(samples):
    plt.subplot(4, 4, idx + 1)
    plt.imshow(X_test[n].reshape(28, 28), cmap = 'Greys', interpolation='nearest')
    plt.title('Label : ' + str(y_test[n]) + ' Predict : ' + str(predicted_labels[n]))
    plt.axis('off')
    
plt.show()

  • 레이블 설명
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    0 티셔츠/탑
    1 바지
    2 풀오버(스웨터의 일종)
    3 드레스
    4 코트
    5 샌들
    6 셔츠
    7 스니커즈
    8 가방
    9 앵클 부츠 
    
  • 비슷하게 생긴게 좀 많아보인다.


4. 요약


4.1 요약

  • 딥러닝의 튜토리얼 MNIST 데이터로 모델을 만들고 예측을 하는 내용이다.
  • 딥러닝은 model 생성하는 모델 구조도를 만드는게 어려울것 같다
  • 특히나 그 구조도는 만들기 나름이라, 많은 공부가 필요할듯 하다
This post is licensed under CC BY 4.0 by the author.

딥러닝 기초 (1) (Basic of Deeplearning 1)

MNIST 데이터로 해보는 CNN (Convolution Neral Network)

Comments powered by Disqus.