CNN Subclassing 모델 학습

In [0]:
# 런타임 -> 런타임 유형변경 -> 하드웨어 가속도 TPU변경
%tensorflow_version 2.x
#런타임 -> 런타임 다시시작
TensorFlow 2.x selected.
In [0]:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

1. Importing Libraries

In [0]:
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

print(tf.__version__)     # 텐서플로우 버전확인 (colab의 기본버전은 1.15.0) --> 2.0 변경 "%tensorflow_version 2.x"
print(keras.__version__)  # 케라스 버전확인
2.1.0
2.2.4-tf

2. Hyper Parameters

In [0]:
learning_rate = 0.001
training_epochs = 15
batch_size = 100

3. MNIST Data

In [0]:
mnist = keras.datasets.mnist
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
In [0]:
# 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) 
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

4. Model Function

In [0]:
# model class 구현
class MNISTModel (tf.keras.Model): # keras.model 구현
    def __init__(self):  # 기본이 되는 층을 구현
        # call the parent constructor(class의 tf.keras.Model) 
        super(MNISTModel, self).__init__() 
        # initialize the layers
        self.conv1 = keras.layers.Conv2D(filters=32, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)
        self.pool1 = keras.layers.MaxPool2D(padding='SAME')
        self.conv2 = keras.layers.Conv2D(filters=64, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)
        self.pool2 = keras.layers.MaxPool2D(padding='SAME')
        self.conv3 = keras.layers.Conv2D(filters=128, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)
        self.pool3 = keras.layers.MaxPool2D(padding='SAME')
        self.pool3_flat = keras.layers.Flatten()
        self.dense4 = keras.layers.Dense(units=256, activation=tf.nn.relu)
        self.drop4 = keras.layers.Dropout(rate=0.4)
        self.dense5 = keras.layers.Dense(units=10, activation=tf.nn.softmax)
    # init에서 만든 층을 불러와서 network 구성 (연산부분을 담당)   
    def call(self, inputs, training=False):  # training : training과 test시에 다르게 동작할 때, true면 둘이 동일하게 사용됨
        net = self.conv1(inputs)
        net = self.pool1(net)
        net = self.conv2(net)
        net = self.pool2(net)
        net = self.conv3(net)
        net = self.pool3(net)
        net = self.pool3_flat(net)
        net = self.dense4(net)
        net = self.drop4(net)
        net = self.dense5(net)
        return net
In [0]:
model = MNISTModel() # model 클래스를 model 객체로 변경
temp_inputs = keras.Input(shape=(28, 28, 1)) # model input image size
model(temp_inputs) # model input
model.summary() # 모델에 대한 요약 출력해줌
Model: "mnist_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 28, 28, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 14, 14, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 7, 7, 128)         73856     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 2048)              0         
_________________________________________________________________
dense (Dense)                (None, 256)               524544    
_________________________________________________________________
dropout (Dropout)            (None, 256)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                2570      
=================================================================
Total params: 619,786
Trainable params: 619,786
Non-trainable params: 0
_________________________________________________________________

5. Training

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

# 학습실행
model.fit(train_images, train_labels,                # 입력값
          batch_size=batch_size,                      # 1회마다 배치마다 100개 프로세스 
          epochs=training_epochs,                     # 15회 학습
          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])
Train on 60000 samples, validate on 10000 samples
Epoch 1/15
60000/60000 [==============================] - 98s 2ms/sample - loss: 0.1946 - accuracy: 0.9387 - val_loss: 0.0415 - val_accuracy: 0.9847
Epoch 2/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0542 - accuracy: 0.9829 - val_loss: 0.0379 - val_accuracy: 0.9873
Epoch 3/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0393 - accuracy: 0.9880 - val_loss: 0.0257 - val_accuracy: 0.9912
Epoch 4/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0317 - accuracy: 0.9902 - val_loss: 0.0202 - val_accuracy: 0.9926
Epoch 5/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0249 - accuracy: 0.9921 - val_loss: 0.0257 - val_accuracy: 0.9917
Epoch 6/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0205 - accuracy: 0.9936 - val_loss: 0.0210 - val_accuracy: 0.9926
Epoch 7/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0174 - accuracy: 0.9945 - val_loss: 0.0227 - val_accuracy: 0.9923
Epoch 8/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0144 - accuracy: 0.9953 - val_loss: 0.0236 - val_accuracy: 0.9920
Epoch 9/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0140 - accuracy: 0.9951 - val_loss: 0.0257 - val_accuracy: 0.9920
Epoch 10/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0125 - accuracy: 0.9959 - val_loss: 0.0252 - val_accuracy: 0.9923
Epoch 11/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0111 - accuracy: 0.9964 - val_loss: 0.0264 - val_accuracy: 0.9922
Epoch 12/15
60000/60000 [==============================] - 97s 2ms/sample - loss: 0.0093 - accuracy: 0.9969 - val_loss: 0.0232 - val_accuracy: 0.9931
Epoch 13/15
60000/60000 [==============================] - 96s 2ms/sample - loss: 0.0081 - accuracy: 0.9974 - val_loss: 0.0291 - val_accuracy: 0.9922
Epoch 14/15
60000/60000 [==============================] - 96s 2ms/sample - loss: 0.0087 - accuracy: 0.9972 - val_loss: 0.0263 - val_accuracy: 0.9924
Epoch 15/15
60000/60000 [==============================] - 96s 2ms/sample - loss: 0.0072 - accuracy: 0.9976 - val_loss: 0.0248 - val_accuracy: 0.9935
Test loss: 0.02476578147190915
Test accuracy: 0.9935