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

1. Importing Libraries

In [0]:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
In [0]:
import tensorflow as tf 
from tensorflow import keras
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 Dataset #########################################################
mnist = keras.datasets.mnist
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
##########################################################################

4. Datasets

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) 

# dataset 인스턴스 만들기(tf.data를 사용하여 데이터셋을 섞고 배치를 만듭니다)
train_dataset = tf.data.Dataset.from_tensor_slices((train_images, train_labels)).shuffle(
                buffer_size=100000).batch(batch_size)
test_dataset = tf.data.Dataset.from_tensor_slices((test_images, test_labels)).batch(batch_size)
# from_tensor_slices : 이미지를 이미지와 라벨로 나누기
# batch : 해당 배치 사이즈 만큼 나누기
# shuffle : 고정된 buffer_size만큼 epoch 마다 이미지를 섞어서 오버피팅이 줄도록 도와줌
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 1s 0us/step

5. Model Function

In [0]:
# Functional 모델 층 구성하기
def create_model():
    inputs = keras.Input(shape=(28, 28, 1))
    conv1 = keras.layers.Conv2D(filters=32, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)(inputs)
    pool1 = keras.layers.MaxPool2D(padding='SAME')(conv1)
    conv2 = keras.layers.Conv2D(filters=64, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)(pool1)
    pool2 = keras.layers.MaxPool2D(padding='SAME')(conv2)
    conv3 = keras.layers.Conv2D(filters=128, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu)(pool2)
    pool3 = keras.layers.MaxPool2D(padding='SAME')(conv3)
    pool3_flat = keras.layers.Flatten()(pool3)
    dense4 = keras.layers.Dense(units=256, activation=tf.nn.relu)(pool3_flat)
    drop4 = keras.layers.Dropout(rate=0.4)(dense4)
    logits = keras.layers.Dense(units=10, activation=tf.nn.softmax)(drop4)
    return keras.Model(inputs=inputs, outputs=logits)
In [0]:
model = create_model() # 모델 함수를 model 객체로 변경
model.summary() # 모델에 대한 요약 출력해줌
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 28, 28, 1)]       0         
_________________________________________________________________
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
_________________________________________________________________
In [0]:
# 위에서 정한 모델을 그림으로(plot) 보여줌
keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_layer_names=True) 
Out[0]:

6. Loss, Optimizer, Accuracy

In [0]:
# 훈련에 필요한 옵티마이저(optimizer)와 손실 함수를 선택합니다
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()        # Loss는 CategoricalCrossentropy
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)    # optimizer는 adam 

# 모델의 손실과 성능을 측정할 지표를 선택합니다. 
# 에포크가 진행되는 동안 수집된 측정 지표를 바탕으로 최종 결과를 출력합니다.
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')

7. Calculating Gradient

In [0]:
# `tf.function` 이 데코레이터는 함수를 "컴파일" 한다.
# tf.GradientTape를 사용하여 모델을 훈련합니다
@tf.function
def train_step(images, labels):
  with tf.GradientTape() as tape:
    predictions = model(images)
    loss = loss_object(labels, predictions)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

  train_loss(loss)
  train_accuracy(labels, predictions)
In [0]:
# 이제 모델을 테스트합니다:
@tf.function
def test_step(images, labels):
  predictions = model(images)
  t_loss = loss_object(labels, predictions)

  test_loss(t_loss)
  test_accuracy(labels, predictions)

8. Training

In [0]:
# train 함수 정의 (텐서플로우 2.0에서는 직접 함수를 만들어야함)
def train(train_dataset, test_dataset, training_epochs):
  for epoch in range(training_epochs):              # 매 epoch 마다 학습이 진행된다
    for images, labels in train_dataset:
      train_step(images, labels)                    # train 이미지 학습

    for test_images, test_labels in test_dataset:   # test 이미지 학습
      test_step(test_images, test_labels)
    
    # print 보여주기 설정
    template = 'epoch: {}, train_loss: {:.4f}, train_acc: {:.2%}, test_loss: {:.4f}, test_acc: {:.2%}'
    print (template.format(epoch+1,
                           train_loss.result(),
                           train_accuracy.result(),
                           test_loss.result(),
                           test_accuracy.result()))
In [0]:
# train 함수 실행, trian data, test data, epoch 순으로 작성
train(train_dataset, test_dataset, training_epochs)
epoch: 1, train_loss: 0.1597, train_acc: 95.00%, test_loss: 0.0508, test_acc: 98.42%
epoch: 2, train_loss: 0.1006, train_acc: 96.84%, test_loss: 0.0456, test_acc: 98.54%
epoch: 3, train_loss: 0.0772, train_acc: 97.57%, test_loss: 0.0391, test_acc: 98.73%
epoch: 4, train_loss: 0.0634, train_acc: 98.01%, test_loss: 0.0370, test_acc: 98.80%
epoch: 5, train_loss: 0.0543, train_acc: 98.28%, test_loss: 0.0369, test_acc: 98.83%
epoch: 6, train_loss: 0.0475, train_acc: 98.49%, test_loss: 0.0352, test_acc: 98.87%
epoch: 7, train_loss: 0.0423, train_acc: 98.66%, test_loss: 0.0334, test_acc: 98.93%
epoch: 8, train_loss: 0.0384, train_acc: 98.78%, test_loss: 0.0336, test_acc: 98.95%
epoch: 9, train_loss: 0.0352, train_acc: 98.88%, test_loss: 0.0326, test_acc: 99.00%
epoch: 10, train_loss: 0.0323, train_acc: 98.97%, test_loss: 0.0317, test_acc: 99.03%
epoch: 11, train_loss: 0.0300, train_acc: 99.04%, test_loss: 0.0313, test_acc: 99.06%
epoch: 12, train_loss: 0.0281, train_acc: 99.10%, test_loss: 0.0309, test_acc: 99.08%
epoch: 13, train_loss: 0.0262, train_acc: 99.16%, test_loss: 0.0312, test_acc: 99.08%
epoch: 14, train_loss: 0.0248, train_acc: 99.21%, test_loss: 0.0313, test_acc: 99.10%
epoch: 15, train_loss: 0.0236, train_acc: 99.25%, test_loss: 0.0312, test_acc: 99.11%