# !pip install seaborn
# !pip install tensorflow==2.2.0
Import the required modules
import numpy as np
import tensorflow as tf
from tensorflow import keras as ks
from keras.layers import Dense
from sklearn.model_selection import train_test_split
Define the training callbacks
- 학습결과를 출력/분석하는 함수 작성
- 손실율을 출력하는 on_epoch_end 메서드
- 손실율 그래프를 그리는 on_train_end 메서드
- 콜백기반
class CustomCallback(ks.callbacks.Callback):
def __init__(self):
self.losses = {}
def on_epoch_end(self, epoch, logs):
self.losses[epoch] = logs['loss']
print('\n==========\n')
print('Epoch:', epoch)
print('Training Loss:', logs['loss'])
print('Validation Loss:', logs['val_loss'])
def on_train_end(self, logs):
import matplotlib.pyplot as plt
plt.plot(self.losses.keys(), self.losses.values())
plt.xlabel('Training Epochs')
plt.ylabel('Training Loss')
plt.ylim([0, 2]) #수렴 여부를 관찰하기 위해 좁은 뷰 설정
plt.show()
self.losses = {}
Declare the model configurations
base_config = {
'model_path': 'model_path',
'model_version': '0',
'dataset_size': 100000,
'test_ratio': 0.33,
'activation': 'relu',
'hiddens': [1],
'epochs': 50,
'batch_size': 1000,
'loss_function': 'mean_squared_error',
'optimizer': 'adam',
'train_callbacks': [CustomCallback()]
}
from copy import copy
config_hidden_1 = copy(base_config)
config_hidden_1['model_version'] = '1'
config_hidden_1['epochs'] = 300
config_hidden_1['hiddens'] = [11, 1]
config_hidden_2 = copy(base_config)
config_hidden_2['model_version'] = '2'
config_hidden_2['hiddens'] = [33, 11, 1]
config_hidden_3 = copy(base_config)
config_hidden_3['model_version'] = '3'
config_hidden_3['hiddens'] = [99, 33, 11, 1]
config_hidden_4_narrowing = copy(base_config)
config_hidden_4_narrowing['model_version'] = '4'
config_hidden_4_narrowing['hiddens'] = [297, 99, 33, 11, 1]
config_hidden_4_expanding = copy(base_config)
config_hidden_4_expanding['model_version'] = '5'
config_hidden_4_expanding['hiddens'] = [11, 33, 99, 297, 1]
Define the cubic function
- 데이터 샘플을 생성하는 함수 작성
def cubic_generator(a, b, c, d, e):
def cubic(x):
'''
입력: 3차원 벡터
출력: 입력 벡터에 대한 3차 함수 계산 값
'''
x1, x2, x3 = x[0], x[1], x[2]
return a + b*x1 + c*x2**2 + d*x3**3 + e
return cubic
cubic_function = cubic_generator(1, 3, 5, 10, 20)
Create the train/test dataset with the cubic function
xs = np.random.uniform(0, 1, (base_config['dataset_size'], 3))
ys = [cubic_function(x) for x in xs]
x_train, x_test, y_train, y_test = train_test_split(xs, ys, test_size=base_config['test_ratio'])
Define the training/evalutaion phase
- KERAS NN으로 model을 구성하는 함수 작성
- KERAS NN을 학습시키는 함수 작성
def train_and_eval(x_train, y_train, x_test, y_test, config):
x_train = np.array(x_train, dtype='float64')
y_train = np.array(y_train, dtype='float64')
x_test = np.array(x_test, dtype='float64')
y_test = np.array(y_test, dtype='float64')
model = ks.models.Sequential()
hiddens = config['hiddens']
for i, hidden in enumerate(hiddens):
if 1 == len(hiddens) or 0 == i:
model.add(Dense(hidden, activation=config['activation'], input_shape=(3,)))
elif i == len(hiddens)-1:
model.add(Dense(hidden))
else:
model.add(Dense(hidden, activation=config['activation']))
model.compile(loss=config['loss_function'], optimizer=config['optimizer'])
print(model.summary())
model.fit(x_train, y_train,
batch_size=config['batch_size'],
epochs=config['epochs'],
verbose=0,
validation_data=(x_test, y_test),
callbacks=[CustomCallback()])
return model
model = train_and_eval(x_train, y_train, x_test, y_test, config_hidden_1)
model = train_and_eval(x_train, y_train, x_test, y_test, config_hidden_2)
model = train_and_eval(x_train, y_train, x_test, y_test, config_hidden_3)
model = train_and_eval(x_train, y_train, x_test, y_test, config_hidden_4_narrowing)
model = train_and_eval(x_train, y_train, x_test, y_test, config_hidden_4_expanding)
Define the prediction function
- 학습된 model에 임의의 입력변수를 입력으로 받아서, y값을 예측하는 함수 작성
def predict(model, x):
x = np.array(x, dtype='float64')
yh = model.predict(x)
return yh
for x in x_test[1:5]:
y_real = cubic_function(x)
y_pred = predict(model, [x])
print('Input:', x)
print('Target:', y_real)
print('Prediction:', y_pred.squeeze(), end='\n\n')
Summary
데이터 샘플 생성방법
-
cubic_genrator(a, b, c, d, e)
:삼차함수를 정의한다. Python 데코레이터 패턴을 사용하여 함수의 계수 값들을 외부에서 설정받는다.
def cubic_generator(a, b, c, d, e):
def cubic(x):
'''
입력: 3차원 벡터
출력: 입력 벡터에 대한 3차 함수 계산 값
'''
x1, x2, x3 = x[0], x[1], x[2]
return a + b*x1 + c*x2**2 + d*x3**3 + e
return cubic
-
데이터 랜덤 샘플
: 3차원 벡터 원소는 균등분포에 따라 0~1 사이값을 랜덤으로 갖도록 했다. 이런 벡터를
dataset_size
갯수만큼 생성한다. 각 벡터에 대응되는 y값은 삼차함수를 호출하여 만든다.xs = np.random.uniform(0, 1, (base_config['dataset_size'], 3)) ys = [cubic_function(x) for x in xs]
Epoch 수
- 에폭 수 설정
- 일반적으로 에폭 수가 증가할 수록 모든 모델의 손실율은 더욱 잘 감소하였다.
- 모델이 깊지 않은 경우(1층) 에폭 수를 크게 잡아도(300) 손실 그래프의 기울기는 평평해지지 않았다
- 모델이 깊을 때(4층), 초반 에폭에 모델이 이미 급격히 수렴되어 평평한 손실 그래프를 보였다
- 학습 시간이 과하지 않도록 깊은 모델에 대해 적당한 에폭 수(50)를 쓰기로 했다
Hidden layer 수와 neuron 수
config_hidden_1['hiddens'] = [11, 1]
config_hidden_2['hiddens'] = [33, 11, 1]
config_hidden_3['hiddens'] = [99, 33, 11, 1]
config_hidden_4_narrowing['hiddens'] = [297, 99, 33, 11, 1]
config_hidden_4_expanding['hiddens'] = [11, 33, 99, 297, 1]
- 히든 레이어 설정
- 1, 2, 3, 4 깊이를 갖는 DNN 모델을 준비하였다. 삼차함수는 non-convex 하므로 히든 레이어를 깊게 쌓아 활성화하면 더 좋은 성능을 낼 것으로 기대했다.
- 입력된 3차원 점의 내재된 의미를 모델이 파악할 수 있도록 고차원 공간으로 사상한다
- 입력 맥락이 가장 잘 남아있는 Input Layer에서 최고차원으로 사상
Activation 함수 선정
- sigmoid, tanh 함수 사용 시
- 4층 짜리 모델이 수렴 되지 않고 1층 짜리 모델과 비슷한 성능을 내는 현상을 관찰하였다
- relu 활성화함수 사용 시
- Vanishing Gradient 문제를 해결하는 ReLU를 사용했다. 덕분에 4층짜리 모델의 학습이 진행된다.
- 또 가장 빠른 수렴속도를 보였기에 ReLU를 활성함수로 채택하였다
The best model
config_hidden_4_narrowing
config_hidden_4_narrowing = {
'model_path': 'model_path',
'model_version': '4',
'dataset_size': 100000,
'test_ratio': 0.33,
'activation': 'relu',
'hiddens': [297, 99, 33, 11, 1],
'epochs': 50,
'batch_size': 1000,
'loss_function': 'mean_squared_error',
'optimizer': 'adam',
'train_callbacks': [CustomCallback()]
}
Epoch: 49
Training Loss: 0.004180582240223885
Validation Loss: 0.004152956418693066
- Vanishing Gradient를 해결하는 ReLU 활성함수 사용
- Non-convex 함수에 잘 fitting 하기 위해서 깊은 히든 레이어 사용
- Input Layer에서부터 입력 확장하며 중요한 정보를 압축해 나가도록 함
- 가중치 갱신 시 모멘텀을 이용하고, 가중치 별 학습률을 조정하는 Adam 옵티마이저 사용
'통계 > Tensorflow2.0 예제' 카테고리의 다른 글
]TensorFlow2[ Estimator를 사용한 비선형회귀 (0) | 2020.11.28 |
---|