CNN Gradient Tape 모델 학습 (브라켓)

※ 텐서플로우 2.0 변환

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

# 예전 방식 : !pip install tensorflow-gpu==2.0.0-rc1
TensorFlow 2.x selected.

1. Data Load

In [0]:
from google.colab import files 

uploaded = files.upload()

for fn in uploaded.keys():
  print('User uploaded file "{name}" with length {length} bytes'.format(
      name=fn, length=len(uploaded[fn])))
Upload widget is only available when the cell has been executed in the current browser session. Please rerun this cell to enable.
Saving data_3000.zip to data_3000.zip
User uploaded file "data_3000.zip" with length 3309996 bytes

드라이브 마운트에 연결하기

In [0]:
from google.colab import drive
drive.mount('/content/drive')
Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly

Enter your authorization code:
··········
Mounted at /content/drive
In [0]:
! mkdir data_3000                        # 마운트에 폴더 생성
! unzip data_3000.zip -d ./data_3000     # unzip

2. 파일 내 이미지 불러오기

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

# 압축해제된 데이터 경로 (마지막 '/' 꼭 붙여야함)
src = './data_3000/'

# 이미지 읽기
def img_read(src,file):
    img = cv.imread(src+file,cv.COLOR_BGR2GRAY)
    return img

# src 경로에 있는 파일 명을 저장합니다. 
files = os.listdir(src)

X,Y = [],[]

# 경로와 파일명을 입력으로 넣어 확인하고 
# 데이터를 255로 나눠서 0~1사이로 정규화 하여 X 리스트에 넣습니다. 
for file in files: 
    X.append(img_read(src,file)/255.)
    Y.append(float(file[:-4]))

# array로 데이터 변환
X = np.array(X)
Y = np.array(Y)

print('X_shape:',np.shape(X[0]),'Y_shape:',np.shape(Y[0]))
print('X_list shape:',np.shape(X),'Y_list shape:',np.shape(Y))
X_shape: (56, 56) Y_shape: ()
X_list shape: (3000, 56, 56) Y_list shape: (3000,)

3. 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

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

4. Hyper Parameters

In [0]:
learning_rate = 0.001  # 러닝레이트 
training_epochs = 15 # 에폭
batch_size = 32        # 배치사이즈
Buffer_size = 100      # 인스턴스 버퍼 사이즈

5. Data Split

In [0]:
import sklearn
from sklearn.model_selection import train_test_split

# Train set, Test set으로 나누기 (80:20으로 나누기)
train_images, test_images, train_labels, test_labels = train_test_split(X,Y, test_size=0.2, random_state=1,shuffle=True)

# CNN input size 변경 (이미지갯수, 56, 56, 1) 차원, 1인 이유는 흑백이라 RGB면 3차원
train_images = train_images.reshape(train_images.shape[0], 56, 56, 1)
test_images = test_images.reshape(test_images.shape[0], 56, 56, 1)

print(np.shape(train_images))
print(np.shape(test_images))

# dataset 인스턴스 만들기
train_dataset = tf.data.Dataset.from_tensor_slices((train_images, train_labels)).shuffle(Buffer_size).batch(batch_size)
test_dataset = tf.data.Dataset.from_tensor_slices((test_images, test_labels)).batch(batch_size)
(2400, 56, 56, 1)
(600, 56, 56, 1)

6. Model Function

In [0]:
# 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=(56, 56, 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(1))   #  Dense층은 답이 1개라 '1'로 설정
    return model
In [0]:
model = create_model() # 모델 함수를 model로 변경
model.summary() # 모델에 대한 요약 출력해줌
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 56, 56, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 28, 28, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 14, 14, 64)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 14, 14, 128)       73856     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 7, 7, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 6272)              0         
_________________________________________________________________
dense (Dense)                (None, 256)               1605888   
_________________________________________________________________
dropout (Dropout)            (None, 256)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 257       
=================================================================
Total params: 1,698,817
Trainable params: 1,698,817
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]:

7. Loss, Optimizer, MAE

In [0]:
loss_object = tf.keras.losses.MeanSquaredError()                     # Loss는 MSE
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)    # optimizer는 adam 

# loss, mae 변수 설정
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_mae = tf.keras.metrics.MeanAbsoluteError(name='train_mae')
test_loss = tf.keras.metrics.Mean(name='test_loss')
test_mae = tf.keras.metrics.MeanAbsoluteError(name='test_mae')

8. Calculating Gradient

In [0]:
# `tf.function` 이 데코레이터는 함수를 "컴파일" 한다.
@tf.function
def train_step(images, labels):
  with tf.GradientTape() as tape:
    predictions = model(images)
    loss = loss_object(labels, predictions)

  # tape에 기록하며 미분이 실행됨
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

  train_loss(loss)
  train_mae(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_mae(labels, predictions)

9. 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_mae: {:.4f}, test_loss: {:.4f}, test_mae: {:.4f}'
    print (template.format(epoch+1,
                           train_loss.result(),
                           train_mae.result(),
                           test_loss.result(),
                           test_mae.result()))
In [0]:
# train 함수 실행, trian data, test data, epoch 순으로 작성
train(train_dataset, test_dataset, training_epochs)
epoch: 1, train_loss: 0.7830, train_mae: 0.4167, test_loss: 0.3777, test_mae: 0.4406
epoch: 2, train_loss: 0.7742, train_mae: 0.4147, test_loss: 0.3746, test_mae: 0.4387
epoch: 3, train_loss: 0.7653, train_mae: 0.4123, test_loss: 0.3720, test_mae: 0.4371
epoch: 4, train_loss: 0.7563, train_mae: 0.4095, test_loss: 0.3690, test_mae: 0.4353
epoch: 5, train_loss: 0.7476, train_mae: 0.4068, test_loss: 0.3687, test_mae: 0.4360
epoch: 6, train_loss: 0.7414, train_mae: 0.4068, test_loss: 0.3660, test_mae: 0.4343
epoch: 7, train_loss: 0.7339, train_mae: 0.4052, test_loss: 0.3668, test_mae: 0.4361
epoch: 8, train_loss: 0.7261, train_mae: 0.4033, test_loss: 0.3640, test_mae: 0.4343
epoch: 9, train_loss: 0.7183, train_mae: 0.4010, test_loss: 0.3628, test_mae: 0.4339
epoch: 10, train_loss: 0.7110, train_mae: 0.3993, test_loss: 0.3610, test_mae: 0.4330
epoch: 11, train_loss: 0.7033, train_mae: 0.3967, test_loss: 0.3585, test_mae: 0.4313
epoch: 12, train_loss: 0.6958, train_mae: 0.3942, test_loss: 0.3559, test_mae: 0.4297
epoch: 13, train_loss: 0.6887, train_mae: 0.3921, test_loss: 0.3533, test_mae: 0.4280
epoch: 14, train_loss: 0.6827, train_mae: 0.3912, test_loss: 0.3519, test_mae: 0.4276
epoch: 15, train_loss: 0.6763, train_mae: 0.3899, test_loss: 0.3502, test_mae: 0.4267