TensorFlow

TensorFlow 기초 24 - MNIST datset (손글씨 이미지 데이터)으로 숫자 이미지 분류 모델 작성(다항분류)

코딩탕탕 2022. 12. 6. 16:18

 

 

# MNIST datset (손글씨 이미지 데이터)으로 숫자 이미지 분류 모델 작성
# MNIST는 숫자 0부터 9까지의 이미지로 구성된 손글씨 데이터셋입니다.
# 총 60,000개의 훈련 데이터와 레이블, 총 10,000개의 테스트 데이터와 레이블로 구성되어 있습니다.
# 레이블은 0부터 9까지 총 10개입니다.

import tensorflow as tf
import numpy as np
import sys

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() # keras.dataset에서 튜플로 반환하므로 ()로 묶었다.
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape) # (60000, 28, 28) (60000,) (10000, 28, 28) (10000,)
print(x_train[0], x_train.shape) # (60000, 28, 28)
print(y_train[0])
# for i in x_train[0]:
#     for j in i:
#         sys.stdout.write('%s  '%j)
#     sys.stdout.write('\n')

# import matplotlib.pyplot as plt
# plt.imshow(x_train[0])
# plt.show()

x_train = x_train.reshape(60000, 784).astype('float32') # reshape함수로 백터로 변환
x_test = x_test.reshape(10000, 784).astype('float32')   # reshape함수로 백터로 변환
# print(x_train[0], x_train[0].shape) # (784,)

# feature data를 정규화
x_train /= 255.0
x_test /= 255.0
# print(x_train[0])
# print(y_train[0], set(y_train))

# label은 원핫 처리 - softmax를 사용하기 때문에
print(y_train[0])
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)
print(y_train[0])

# train data의 일부를 validation data로 사용하기
x_val = x_train[50000:60000] # 10000개는 validation
y_val = y_train[50000:60000]

x_train = x_train[0:50000] # 50000개는 train
y_train = y_train[0:50000]
print(x_val.shape, x_train.shape) # (10000, 784) (50000, 784)

# model
from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten, Dropout

model = Sequential()

# model.add(Dense(units=128, input_dim=784))
# model.add(Flatten(input_shape=(28, 28))) # reshape를 하지 않은 경우 Flatten에 의해 784로 변환된다.
# model.add(Dense())
# model.add(Activation('relu'))
# model.add(Dropout(rate=0.2))

"""
model.add(Dense(units=128, input_dim=784))
model.add(Activation('relu'))
model.add(Dropout(rate=0.2)) # 20%는 학습에 참여하지 말아라는 의미

model.add(Dense(units=128))
model.add(Activation('relu'))
model.add(Dropout(rate=0.2)) # 20%는 학습에 참여하지 말아라는 의미

model.add(Dense(units=10)) # 출력층
model.add(Activation('softmax'))
"""

model.add(Dense(units=128, input_dim=784, activation='relu'))
# model.add(Flatten(input_shape=(28, 28))) # reshape를 하지 않은 경우 Flatten에 의해 784로 변환된다.
model.add(Dropout(rate=0.2)) # 20%는 학습에 참여하지 말아라는 의미

model.add(Dense(units=128, activation='relu'))
model.add(Dropout(rate=0.2)) # 20%는 학습에 참여하지 말아라는 의미

model.add(Dense(units=10, activation='softmax'))

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(model.summary())

history = model.fit(x_train, y_train, epochs=10, batch_size=128, validation_data=(x_val, y_val), verbose=0)
print(history.history.keys())
print('loss :', history.history['loss'])
print('val_loss :', history.history['val_loss'])
print('accuracy :', history.history['accuracy'])
print('val_accuracy :', history.history['val_accuracy'])

# 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.xlabel('epochs')
plt.legend()
plt.show()

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.xlabel('epochs')
plt.legend()
plt.show()

# 모델 평가
score = model.evaluate(x_test, y_test, batch_size=128, verbose=0)
print('final loss :',score[0])
print('final accuracy :',score[1])

model.save('cla7_model.hdf5') # 확장자를 보고 model이라고 판단 가능하다.

# 여기서부터는 저장된 모델로 새로운 데이터에 대한 이미지 분류 작업 진행
mymodel = tf.keras.models.load_model('cla7_model.hdf5')

pred = mymodel.predict(x_train[:1])
print('pred :', pred) # 확률값이 출력
print('예측값 :', np.argmax(pred, 1)) # 확률값 중 가장 큰 인덱스를 분류 결과로 얻음
print('실제값 :', y_train[:1])
print('실제값 :', np.argmax(y_train[:1], 1))




<console>
(60000, 28, 28) (60000,) (10000, 28, 28) (10000,)
[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136
  175  26 166 255 247 127   0   0   0   0]
 [  0   0   0   0   0   0   0   0  30  36  94 154 170 253 253 253 253 253
  225 172 253 242 195  64   0   0   0   0]
 [  0   0   0   0   0   0   0  49 238 253 253 253 253 253 253 253 253 251
   93  82  82  56  39   0   0   0   0   0]
 [  0   0   0   0   0   0   0  18 219 253 253 253 253 253 198 182 247 241
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  80 156 107 253 253 205  11   0  43 154
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0  14   1 154 253  90   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 139 253 190   2   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0  11 190 253  70   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  35 241 225 160 108   1
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0  81 240 253 253 119
   25   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  45 186 253 253
  150  27   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  16  93 252
  253 187   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 249
  253 249  64   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  46 130 183 253
  253 207   2   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  39 148 229 253 253 253
  250 182   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0  24 114 221 253 253 253 253 201
   78   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  23  66 213 253 253 253 253 198  81   2
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0  18 171 219 253 253 253 253 195  80   9   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0  55 172 226 253 253 253 253 244 133  11   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 136 253 253 253 212 135 132  16   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]] (60000, 28, 28)
5
5
[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
(10000, 784) (50000, 784)
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 128)               100480    
                                                                 
 dropout (Dropout)           (None, 128)               0         
                                                                 
 dense_1 (Dense)             (None, 128)               16512     
                                                                 
 dropout_1 (Dropout)         (None, 128)               0         
                                                                 
 dense_2 (Dense)             (None, 10)                1290      
                                                                 
=================================================================
Total params: 118,282
Trainable params: 118,282
Non-trainable params: 0
_________________________________________________________________
None
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
loss : [0.4403969943523407, 0.19961883127689362, 0.1470498889684677, 0.11703752726316452, 0.09893597662448883, 0.08715160936117172, 0.07764007151126862, 0.06841342151165009, 0.06573114544153214, 0.061331573873758316]
val_loss : [0.17090469598770142, 0.12302819639444351, 0.10522539913654327, 0.09100259095430374, 0.08063910156488419, 0.07660463452339172, 0.07578850537538528, 0.08383689075708389, 0.0760139748454094, 0.07369726896286011]
accuracy : [0.8688200116157532, 0.9401599764823914, 0.9548599720001221, 0.9643200039863586, 0.9691600203514099, 0.9724799990653992, 0.9759799838066101, 0.9785199761390686, 0.9789800047874451, 0.9796599745750427]
val_accuracy : [0.949999988079071, 0.9624999761581421, 0.9692000150680542, 0.9729999899864197, 0.9764000177383423, 0.9771000146865845, 0.9785000085830688, 0.9764000177383423, 0.9781000018119812, 0.978600025177002]
final loss : 0.06710246950387955
final accuracy : 0.9785000085830688

1/1 [==============================] - ETA: 0s
1/1 [==============================] - 0s 41ms/step
pred : [[4.0980396e-14 8.1789928e-08 6.1205583e-09 3.1447946e-03 5.4112692e-18
  9.9685502e-01 1.8860232e-12 3.5345428e-11 3.6873602e-13 2.6834346e-08]]
예측값 : [5]
실제값 : [[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]]
실제값 : [5]

reshape를 하지 않은 경우 Flatten 함수에 의해 784로 변환된다.(28, 28)

 

Drop-out은 어떤 특정한 설명변수 Feature만을 과도하게 집중하여 학습함으로써 발생할 수 있는 과대적합(Overfitting)을 방지하기 위해 사용한다. 히든레이어에만 부여한다.

 

 

loss, val_loss 시각화

 

 

acc, val_acc 시각화