0. NN Implementation Flow in TensorFlow
1. Set hyper parameters
; learning rate, training epochs, batch size, ect.
2. Make a data pipelining
; use tf.data
# data pipeline이란 데이터 셋을 load하고, 앞에서 설정했던 batch_size만큼 테이터를 가져 와서 네트워크에 공급하는 역할
3. Build a neural network model
; tf.keras의 subclassing 사용
4. Define a loss function
; cross entropy
# 뉴럴 네트워크의 output과 우리가 가진 정답(label)간의 error비교
# classification 문제를 풀어볼 것이므로 cross entropy를 사용
5. Calculate a gradient
; use tf.GradientTape
# loss값을 weight에 대해 미분해 Gradient를 계산
6. Select an optimizer
; Adam optimizer
# Gradient를 이용해 weight를 update
# ---------------------------------------- 여기까지가 사실상 학습부분
7. Define a metric for model's performance
; accuracy
# 테스트 데이터 셋을 이용하여 모델이 얼마나 잘 학습했는지 확인을 위한 성능 측정 metric
# Classification 문제에서는 metric으로 accuracy를 많이 사용
8. (optional) Make a checkpoint for saving
9. Train and Validate a neural network model
Ensemble로 CNN model을 구성해보고자 한다. 지난 포스팅과 비교하여 코드가 변경되는 부분은 빨간색으로 표시한 부분이다. 3번은 subclassing model에서 인스턴스를 여러 개 생성하는 코드가 수정될 것이며, 7번의 accuracy를 계사하는 부분에 있어서도 모델에 대한 output이 여러 개가 나올 것이므로 그 output을 종합하여 정확도를 계산하는 코드로 변경될 것이며, model이 여러 개 있으므로 9번의 training코드도 변경시켜줘야한다.
여기서는 세 개의 CNN으로 Ensemble을 아래와 같이 구성할 것이다.
똑같은 데이터 셋을 세 개를 각각의 모델에 넣어줘 각각 학습을 실행시키고,
학습하는 중간중간 혹은 학습이 모두 끝난 다음에 inference할 때는 같은 이미지를 넣었을 때 출력되는 각각의 모델의 output을 종합적으로 판단하는 방식
1. Importing Libraries
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt
import os
print(tf.__version__)
print(keras.__version__)
2. Hyper Parameters
learning_rate = 0.001
training_epochs = 15
batch_size = 100
tf.random.set_seed(777)
3. Creating Checkpoint Directory
cur_dir = os.getcwd()
ckpt_dir_name = 'checkpoints'
model_dir_name = 'minst_cnn_emsemble'
checkpoint_dir = os.path.join(cur_dir, ckpt_dir_name, model_dir_name)
os.makedirs(checkpoint_dir, exist_ok=True)
checkpoint_prefix = os.path.join(checkpoint_dir, model_dir_name)
4. MNIST / Fashion MNIST Data
## MNIST Dataset #########################################################
mnist = keras.datasets.mnist
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
##########################################################################
## Fashion MNIST Dataset #################################################
#mnist = keras.datasets.fashion_mnist
#class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
##########################################################################
5. Datasets
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.astype(np.float32) / 255.
test_images = test_images.astype(np.float32) / 255.
train_images = np.expand_dims(train_images, axis=-1)
test_images = np.expand_dims(test_images, axis=-1)
train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)
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)
6. Model Class-Model Subclassing
class MNISTModel(tf.keras.Model):
def __init__(self):
super(MNISTModel, self).__init__()
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)
def call(self, inputs, training=False):
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
# 위의 call 메서드까지는 동일하나 변경되는 부분은 이 부분이다.
# 여러 개의 model을 만들 것이므로 models라는 빈 리스트를 임의로 만들어주고,
# for문을 돌면서 인스턴스를 하나씩 생성해 리스트에 append하는 방식이다.
# 앞서 말했듯 3개의 모델을 만들 것이므로 num_models는 3
models = []
num_models = 3
for m in range(num_models):
models.append(MNISTModel())
7. Loss Function
모델이 여러 개가 되었지만 loss function이나 gradient를 모델 하나하나에 대해 따로 계산을 할 것이므로 코드 이 두 부분에 대한 코드 변경은 없다.
def loss_fn(model, images, labels):
logits = model(images, training=True)
loss = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(
y_pred=logits, y_true=labels, from_logits=True))
return loss
8. Calculating Gradient
def grad(model, images, labels):
with tf.GradientTape() as tape:
loss = loss_fn(model, images, labels)
return tape.gradient(loss, model.variables)
9. Calculating Model's Accuracy
# 앞서 말했듯 평가 부분에서 여러 모델을 종합해서 평가하므로 model이 아닌 앞에서 만들었던 models 리스트를 파라미터로 넣어줘야한다.
def evaluate(models, images, labels):
# 여기의 predictions이 모델 세 개에서 나온 아웃풋을 종합한 결과를 나타낸다.
# 처음에는 labels와 같은 shape의 0으로 채워진 tensor을 만들어 놓고
predictions = np.zeros_like(labels)
# for문으로 models의 리스트에서 모델을 하나씩 꺼내서 그 모델에다가 이미지를 넣어준다.
for model in models:
logits = model(images, training=False)
predictions += logits # 각 모델에서 나온 logits을 predictions에 더함
# 앙상블 기법을 구현하는 방법은 여러 가지가 있는데, 여기서는 간단하게 각 모델에서 나온 결과를 다 더해서 그 중에 가장 큰 것이 정답이라고 하는 방법을 사용한다.
correct_prediction = tf.equal(tf.argmax(predictions, 1), tf.argmax(labels, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
return accuracy
10. Optimizer
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
11. Creating Checkpoints
# checkpoints는 모델 별로 따로 저장하기 위해서 리스트 형태로 만들어 주었다.
checkpoints = []
for m in range(num_models):
checkpoints.append(tf.train.Checkpoint(cnn=models[m]))
12. Training
# 기존은 for문은 2개(바깥쪽 for문은 epoch 하나마다 루프를 한 번 도는 것이고 안쪽 for문은 batch 한 번에 한 번 루프를 도는 형식)를 썼지만,
# 여기서는 batch안에서도 각각의 모델이 학습할 수 있도록 for문 세 개를 사용한다.
# train my model
print('Learning started. It takes sometime.')
for epoch in range(training_epochs):
avg_loss = 0.
avg_train_acc = 0.
avg_test_acc = 0.
train_step = 0
test_step = 0
for images, labels in train_dataset:
for model in models:
#train(model, images, labels)
grads = grad(model, images, labels)
optimizer.apply_gradients(zip(grads, model.variables))
loss = loss_fn(model, images, labels)
avg_loss += loss / num_models # loss를 계산할 때 모델의 숫자로 나눠준다는 점을 주의!
acc = evaluate(models, images, labels) # 첫 번째 파라미터 models 리스트
avg_train_acc += acc
train_step += 1
avg_loss = avg_loss / train_step
avg_train_acc = avg_train_acc / train_step
for images, labels in test_dataset:
acc = evaluate(models, images, labels) # 첫 번째 파라미터 models 리스트
avg_test_acc += acc
test_step += 1
avg_test_acc = avg_test_acc / test_step
print('Epoch:', '{}'.format(epoch + 1), 'loss =', '{:.8f}'.format(avg_loss),
'train accuracy = ', '{:.4f}'.format(avg_train_acc),
'test accuracy = ', '{:.4f}'.format(avg_test_acc))
for idx, checkpoint in enumerate(checkpoints):
checkpoint.save(file_prefix=checkpoint_prefix+'-{}'.format(idx))
print('Learning Finished!')
참고자료
https://www.edwith.org/boostcourse-dl-tensorflow/lecture/43747/
'IT > AI\ML' 카테고리의 다른 글
[python/Tensorflow2.0] RNN(Recurrent Neural Network) ; basic (0) | 2020.04.21 |
---|---|
[python/Tensorflow2.0] Mnist 학습 모델 (4)-CNN; Best CNN (0) | 2020.04.21 |
[python/Tensorflow2.0] Mnist 학습 모델 (2)-CNN;Sequential, Functional, Model Subclassing (0) | 2020.04.20 |
[python/Tensorflow2.0] Mnist 학습 모델 (1)-DNN(Deep Neural Network) (0) | 2020.04.20 |
[python/OpenCV] 이미지 처리 예제 Q31~Q35 (1) | 2020.04.20 |