CNN Sequential 모델 학습

1.라이브러리 읽어 들이기

In [ ]:
## load modules
import tensorflow as tf 
from tensorflow import keras
from tensorflow.keras.utils import to_categorical # one-hot 인코딩
import numpy as np
import matplotlib.pyplot as plt
import os
import matplotlib.pyplot as plt

print("tf.__version__")     # 텐서플로우 버전확인 
2.2.0

2. 데이터 준비

In [ ]:
mnist = keras.datasets.mnist
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
In [ ]:
# MNIST image load (trian, test)
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()    

# 0~255 중 하나로 표현되는 입력 이미지들의 값을 1 이하가 되도록 정규화    
train_images = train_images.astype(np.float32) / 255.
test_images = test_images.astype(np.float32) / 255.

# np.expand_dims 차원을 변경
train_images = np.expand_dims(train_images, axis=-1)
test_images = np.expand_dims(test_images, axis=-1)

# label을 ont-hot encoding    
train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10) 
In [ ]:
learning_rate = 0.001
training_epochs = 50
batch_size = 100
In [ ]:
# images 확인용
plt.imshow(train_images[0,:,:,0],cmap = 'gray')
Out[ ]:
<matplotlib.image.AxesImage at 0x7f8ca2dcda90>

3. 모델링

CNN Network 구성

In [ ]:
# Sequential 모델 층 구성하기
def create_model():
    model = keras.Sequential() # Sequential 모델 시작
    model.add(keras.layers.Conv2D(filters=32, kernel_size=3, activation=tf.nn.relu, padding='SAME', 
                                  input_shape=(28, 28, 1)))
    model.add(keras.layers.MaxPool2D(padding='SAME'))
    model.add(keras.layers.Conv2D(filters=64, kernel_size=3, activation=tf.nn.relu, padding='SAME'))
    model.add(keras.layers.MaxPool2D(padding='SAME'))
    model.add(keras.layers.Conv2D(filters=128, kernel_size=3, activation=tf.nn.relu, padding='SAME'))
    model.add(keras.layers.MaxPool2D(padding='SAME'))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(256, activation=tf.nn.relu))
    model.add(keras.layers.Dropout(0.4))
    model.add(keras.layers.Dense(10, activation=tf.nn.softmax))
    return model
In [ ]:
model = create_model() # 모델 함수를 model로 변경
model.summary() # 모델에 대한 요약 출력해줌
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 28, 28, 32)        320       
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 14, 14, 64)        18496     
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 7, 7, 64)          0         
_________________________________________________________________
conv2d_8 (Conv2D)            (None, 7, 7, 128)         73856     
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 4, 4, 128)         0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 2048)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 256)               524544    
_________________________________________________________________
dropout_2 (Dropout)          (None, 256)               0         
_________________________________________________________________
dense_5 (Dense)              (None, 10)                2570      
=================================================================
Total params: 619,786
Trainable params: 619,786
Non-trainable params: 0
_________________________________________________________________
In [ ]:
# 위에서 정한 모델을 그림으로(plot) 보여줌
keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True)
Out[ ]:

4. 학습 및 실행

In [ ]:
# CNN 모델 구조 확정하고 컴파일 진행
model.compile(loss='categorical_crossentropy',       # crossentropy loss
              optimizer='adam',                      # adam optimizer
              metrics=['accuracy'])                  # 측정값 : accuracy

# 학습실행
history = model.fit(train_images, train_labels,       # 입력값
          batch_size=batch_size,                      # 1회마다 배치마다 100개 프로세스 
          epochs=training_epochs,                     # 50회 학습
          verbose=1,                                  # verbose는 학습 중 출력되는 문구를 설정하는 것 
          validation_data=(test_images, test_labels)) # test를 val로 사용
          
# test 값 결과 확인
score = model.evaluate(test_images, test_labels, verbose=0) # verbose가 0 이면 ==== 움직이지 않고, 1이면 ==== 진행 바가 움직임
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Epoch 1/50
600/600 [==============================] - 3s 5ms/step - loss: 0.1978 - accuracy: 0.9378 - val_loss: 0.0418 - val_accuracy: 0.9853
Epoch 2/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0546 - accuracy: 0.9833 - val_loss: 0.0319 - val_accuracy: 0.9899
Epoch 3/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0380 - accuracy: 0.9882 - val_loss: 0.0259 - val_accuracy: 0.9912
Epoch 4/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0305 - accuracy: 0.9909 - val_loss: 0.0242 - val_accuracy: 0.9916
Epoch 5/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0256 - accuracy: 0.9919 - val_loss: 0.0214 - val_accuracy: 0.9925
Epoch 6/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0208 - accuracy: 0.9934 - val_loss: 0.0203 - val_accuracy: 0.9932
Epoch 7/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0174 - accuracy: 0.9944 - val_loss: 0.0200 - val_accuracy: 0.9933
Epoch 8/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0127 - accuracy: 0.9959 - val_loss: 0.0220 - val_accuracy: 0.9937
Epoch 9/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0147 - accuracy: 0.9949 - val_loss: 0.0242 - val_accuracy: 0.9927
Epoch 10/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0112 - accuracy: 0.9963 - val_loss: 0.0252 - val_accuracy: 0.9922
Epoch 11/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0110 - accuracy: 0.9962 - val_loss: 0.0312 - val_accuracy: 0.9914
Epoch 12/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0095 - accuracy: 0.9968 - val_loss: 0.0246 - val_accuracy: 0.9929
Epoch 13/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0088 - accuracy: 0.9971 - val_loss: 0.0287 - val_accuracy: 0.9926
Epoch 14/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0081 - accuracy: 0.9972 - val_loss: 0.0323 - val_accuracy: 0.9912
Epoch 15/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0082 - accuracy: 0.9972 - val_loss: 0.0283 - val_accuracy: 0.9925
Epoch 16/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0070 - accuracy: 0.9977 - val_loss: 0.0249 - val_accuracy: 0.9935
Epoch 17/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0070 - accuracy: 0.9977 - val_loss: 0.0299 - val_accuracy: 0.9918
Epoch 18/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0055 - accuracy: 0.9982 - val_loss: 0.0251 - val_accuracy: 0.9933
Epoch 19/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0078 - accuracy: 0.9975 - val_loss: 0.0247 - val_accuracy: 0.9938
Epoch 20/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0044 - accuracy: 0.9985 - val_loss: 0.0235 - val_accuracy: 0.9936
Epoch 21/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0049 - accuracy: 0.9983 - val_loss: 0.0330 - val_accuracy: 0.9924
Epoch 22/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0070 - accuracy: 0.9977 - val_loss: 0.0267 - val_accuracy: 0.9942
Epoch 23/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0044 - accuracy: 0.9985 - val_loss: 0.0256 - val_accuracy: 0.9947
Epoch 24/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0047 - accuracy: 0.9985 - val_loss: 0.0251 - val_accuracy: 0.9937
Epoch 25/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0033 - accuracy: 0.9988 - val_loss: 0.0333 - val_accuracy: 0.9929
Epoch 26/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0039 - accuracy: 0.9987 - val_loss: 0.0393 - val_accuracy: 0.9916
Epoch 27/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0075 - accuracy: 0.9978 - val_loss: 0.0265 - val_accuracy: 0.9935
Epoch 28/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0032 - accuracy: 0.9989 - val_loss: 0.0320 - val_accuracy: 0.9935
Epoch 29/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0045 - accuracy: 0.9987 - val_loss: 0.0265 - val_accuracy: 0.9939
Epoch 30/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0034 - accuracy: 0.9990 - val_loss: 0.0402 - val_accuracy: 0.9928
Epoch 31/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0052 - accuracy: 0.9983 - val_loss: 0.0497 - val_accuracy: 0.9914
Epoch 32/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0037 - accuracy: 0.9990 - val_loss: 0.0350 - val_accuracy: 0.9932
Epoch 33/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0040 - accuracy: 0.9987 - val_loss: 0.0374 - val_accuracy: 0.9930
Epoch 34/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0041 - accuracy: 0.9985 - val_loss: 0.0348 - val_accuracy: 0.9932
Epoch 35/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0039 - accuracy: 0.9988 - val_loss: 0.0366 - val_accuracy: 0.9935
Epoch 36/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0029 - accuracy: 0.9990 - val_loss: 0.0387 - val_accuracy: 0.9940
Epoch 37/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0044 - accuracy: 0.9985 - val_loss: 0.0280 - val_accuracy: 0.9945
Epoch 38/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0045 - accuracy: 0.9987 - val_loss: 0.0328 - val_accuracy: 0.9941
Epoch 39/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0025 - accuracy: 0.9992 - val_loss: 0.0386 - val_accuracy: 0.9939
Epoch 40/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0027 - accuracy: 0.9992 - val_loss: 0.0409 - val_accuracy: 0.9930
Epoch 41/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0037 - accuracy: 0.9990 - val_loss: 0.0419 - val_accuracy: 0.9929
Epoch 42/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0032 - accuracy: 0.9988 - val_loss: 0.0355 - val_accuracy: 0.9944
Epoch 43/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0043 - accuracy: 0.9988 - val_loss: 0.0440 - val_accuracy: 0.9935
Epoch 44/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0025 - accuracy: 0.9991 - val_loss: 0.0457 - val_accuracy: 0.9935
Epoch 45/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0035 - accuracy: 0.9990 - val_loss: 0.0360 - val_accuracy: 0.9933
Epoch 46/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0035 - accuracy: 0.9990 - val_loss: 0.0469 - val_accuracy: 0.9935
Epoch 47/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0046 - accuracy: 0.9988 - val_loss: 0.0422 - val_accuracy: 0.9934
Epoch 48/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0024 - accuracy: 0.9993 - val_loss: 0.0444 - val_accuracy: 0.9932
Epoch 49/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0018 - accuracy: 0.9994 - val_loss: 0.0516 - val_accuracy: 0.9938
Epoch 50/50
600/600 [==============================] - 3s 4ms/step - loss: 0.0063 - accuracy: 0.9983 - val_loss: 0.0493 - val_accuracy: 0.9925
Test loss: 0.04926709085702896
Test accuracy: 0.9925000071525574

5. 학습 그래프 그리기

In [ ]:
import matplotlib.pyplot as plt
import numpy as np
import os

# 모델 학습 후 정보가 담긴 history 내용을 토대로 선 그래프를 그리는 함수 설정

def plot_acc(history, title=None):        # Accuracy(정확도) Visualization
    # summarize history for accuracy
    if not isinstance(history, dict):
        history = history.history

    plt.plot(history['accuracy'])        # accuracy
    plt.plot(history['val_accuracy'])    # validation accuracy
    if title is not None:
        plt.title(title)
    plt.ylabel('Accracy')
    plt.xlabel('Epoch')
    plt.legend(['Training data', 'Validation data'], loc=0)
    # plt.show()


def plot_loss(history, title=None):     # Loss Visualization
    # summarize history for loss
    if not isinstance(history, dict):
        history = history.history

    plt.plot(history['loss'])           # loss
    plt.plot(history['val_loss'])       # validation
    if title is not None:
        plt.title(title)
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Training data', 'Validation data'], loc=0)
    # plt.show()
In [ ]:
# Visualization
plot_acc(history, '(a) Accuracy')  # 학습 경과에 따른 정확도 변화 추이
plt.show()
plot_loss(history, '(b) Loss')     # 학습 경과에 따른 손실값 변화 추이
plt.show()

6. 예측하기

In [ ]:
pred = model.predict(test_images)
plt.imshow(test_images[0,:,:,0], cmap='gray');
print(test_labels[0])
print(pred[0])
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[8.3033055e-37 3.5279807e-25 9.1266421e-28 2.4915148e-31 3.8705204e-24
 5.5013606e-35 0.0000000e+00 1.0000000e+00 3.5599098e-34 2.5713820e-21]