신경망에는 다수의 하이퍼파라미터가 등장합니다.
각 층의 뉴런 수, 배치 크기, 매개변수 갱신 시의 학습률, 가중치 감소 등이 하이퍼파라미터입니다.
하이퍼파라미터의 값을 어떻게 결정하느냐에 따라 학습 모델의 성능이 크게 영향을 받습니다.
그럼 하이퍼파라미터의 값을 최대한 효율적으로 탐색하는 방법을 알아보겠습니다.
# 검증 데이터
하이퍼파라미터를 다양한 값으로 설정하고 검증하기 전에 검증하는 과정, 성능을 평가하는 과정에 대해 먼저 소개하겠습니다.
하이퍼파라미터의 성능을 평가할 때는 시험 test 데이터를 사용하면 안됩니다.
시험 데이터를 사용하면 하이퍼파라미터가 시험 데이터에 오버피팅됩니다.
시험 데이터에만 적합하게 조정되어 다른 데이터에는 적용하지 못하는 범용 성능이 떨어지는 모델이 될 수 있기 때문입니다.
그래서 하파를 조정할 때는 하파 전용 확인 데이터가 필요합니다.
(하이퍼.. 하이퍼파라미터라고 언급하기 어려우니 이제 하파라고 줄여쓰겠습니다...양해 부탁드려요.)
하파 조정용 데이터를 일반적으로 검증 데이터 Validation data라고 부릅니다. 이 데이터로 하파의 적절성을 평가합니다.
훈련 데이터: 매개변수(가중치 & 편향)의 학습에 이용,
검증 데이터: 하이퍼파라미터 성능 평가에 이용,
시험 데이터: 신경망의 범용 성능 평가에 이용합니다.
그동안에는 MNIST 데이터셋을 훈련 데이터와 시험 데이터로만 분리해놨었습니다.
MNIST 데이터셋에서 검증 데이터를 얻기 위해 훈련 데이터 중 20% 정도를 검증 데이터로 먼저 분리하려고 합니다.
파이썬 코드로는 다음과 같습니다.
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
# 훈련 데이터를 분리하기 전에 입력 데이터와 정답 레이블을 뒤섞는다.
# 데이터셋 안의 데이터가 치우쳐있을 수 있기 때문이다. (오름차순으로 숫자가 정렬되어 있거나)
x_train, t_train = shuffle_dataset(x_train, t_train)
# 20%를 검증 데이터로 분할
validation_rate = 0.20
validation_num = int(x_train.shape[0] * validation_rate)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]
위의 코드에서 사용한 shuffle_dataset 함수는 아래와 같이 정의된다.
def shuffle_dataset(x, t):
"""데이터셋을 뒤섞는다.
Parameters
----------
x : 훈련 데이터
t : 정답 레이블
Returns
-------
x, t : 뒤섞은 훈련 데이터와 정답 레이블
"""
permutation = np.random.permutation(x.shape[0])
x = x[permutation,:] if x.ndim == 2 else x[permutation,:,:,:]
t = t[permutation]
return x, t
이제 하파를 최적화하고 검증할 준비를 완료했습니다.
# 하이퍼파라미터 최적화
하파 최적화의 핵심은 하파의 '최적값'이 존재하는 범위를 조금씩 줄여나가는 것입니다.
범위를 줄이기 위해 대략적 범위를 먼저 설정하고 그 범위 내에서 무작위로 하파 값을 고르고 (샘플링)
그 값으로 정확도 accuracy를 평가합니다.
위 작업을 여러번 반복하면서 하파의 최적값 범위를 좁혀서 최적화합니다.
신경망의 하이퍼파라미터 최적화에서는 그리드 서치 grid search 같은 규칙적 탐색보단 무작위 샘플링 탐색이 더 좋은 결과를 낸다고 통상적으로 알려져 있습니다.
하파 최적화할 때 딥러닝 학습에 굉장히 오랜 시간이 걸립니다. 따라서 최적화가 잘 안된다 싶으면 일찍 포기하는 게 좋습니다. 그래서 보통은 학습을 위한 에폭을 작게 해서, 1회 평가에 걸리는 시간을 단축하는 것이 효과적입니다.
정리하면 하파 최적화는 0~3단계로 구성됩니다.
-
0단계 - 하이퍼파라미터 값의 범위를 설정
-
1단계 - 설정된 범위에서 하이퍼파라미터의 값을 무작위로 추출
-
2단계 - 1단계에서 샘플링한 하이퍼파라미터 값을 사용하여 학습하고, 검증 데이터로 정확도를 평가
(단, 에폭은 작게 설정)
-
3단계 - 1단계와 2단계를 특정 횟수 (100회 등) 반복하며, 그 정확도의 결과를 보고 하이퍼파라미터의 범위를 좁힘
위 단계를 반복하여 범위를 좁히고 충분히 좁혀지면 그 범위 내에서 값을 하나 고릅니다.
[참고]
위에서 소개한 하이퍼파라미터 최적화 방법은 직관적이고 실용적인 방법입니다. 더 수학 이론을 구사한 효율적인 최적화 기법으로는 베이즈 최적화 Bayesian optimization가 있습니다.
# 하이퍼파라미터 최적화 구현
MNIST 데이터셋으로 하파 최적화를 직접 구현해봅시다.
하파 중 '학습률'과 '가중치 감소의 세기를 조절하는 계수 (가중치 감소 계수)'를 탐색하는 문제를 풀어보겠습니다.
하파 검증을 위해 가중치 감소 계수는 (1e-8 ~ 1e-4) 사이,
학습률은 (1e-6 ~ 1e-2) 사이의 로그 스케일 범위로 무작위 추출해 수행합니다.
파이썬 코드로는 다음과 같이 구현할 수 있습니다.
weight_decay = 10 ** np.random.uniform(-8,-4)
lr = 10 ** np.random.uniform(-6,-2) # learning rate
위와 같이 무작위로 추출한 값을 이용해 학습을 수행합니다.
후에는 다양한 하파 값으로 학습을 반복하며 신경망에 좋을 것 같은 값이 어디에 존재하는지 관찰합니다.
파이썬 코드로 다음과 같이 구성하고 결과를 보겠습니다.
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net import MultiLayerNet
from common.util import shuffle_dataset
from common.trainer import Trainer
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
# 결과를 빠르게 얻기 위해 훈련 데이터를 줄임
x_train = x_train[:500]
t_train = t_train[:500]
# 20%를 검증 데이터로 분할
validation_rate = 0.20
validation_num = int(x_train.shape[0] * validation_rate)
x_train, t_train = shuffle_dataset(x_train, t_train)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]
def __train(lr, weight_decay, epocs=50):
network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100],
output_size=10, weight_decay_lambda=weight_decay)
trainer = Trainer(network, x_train, t_train, x_val, t_val,
epochs=epocs, mini_batch_size=100,
optimizer='sgd', optimizer_param={'lr': lr}, verbose=False)
trainer.train()
return trainer.test_acc_list, trainer.train_acc_list
# 하이퍼파라미터 무작위 탐색======================================
optimization_trial = 100
results_val = {}
results_train = {}
for _ in range(optimization_trial):
# 탐색한 하이퍼파라미터의 범위 지정===============
weight_decay = 10 ** np.random.uniform(-8, -4)
lr = 10 ** np.random.uniform(-6, -2)
# ================================================
val_acc_list, train_acc_list = __train(lr, weight_decay)
print("val acc:" + str(val_acc_list[-1]) + " | lr:" + str(lr) + ", weight decay:" + str(weight_decay))
key = "lr:" + str(lr) + ", weight decay:" + str(weight_decay)
results_val[key] = val_acc_list
results_train[key] = train_acc_list
# 그래프 그리기========================================================
print("=========== Hyper-Parameter Optimization Result ===========")
graph_draw_num = 20
col_num = 5
row_num = int(np.ceil(graph_draw_num / col_num))
i = 0
for key, val_acc_list in sorted(results_val.items(), key=lambda x:x[1][-1], reverse=True):
print("Best-" + str(i+1) + "(val acc:" + str(val_acc_list[-1]) + ") | " + key)
plt.subplot(row_num, col_num, i+1)
plt.title("Best-" + str(i+1))
plt.ylim(0.0, 1.0)
if i % 5: plt.yticks([])
plt.xticks([])
x = np.arange(len(val_acc_list))
plt.plot(x, val_acc_list)
plt.plot(x, results_train[key], "--")
i += 1
if i >= graph_draw_num:
break
plt.show()
가중치 감소 계수의 범위를 1e-8 ~ 1e-4, 학습률의 범위를 1e-6 ~ 1e-2로 하여 실험했을 때, 검증 데이터의 학습 추이를 정확도가 높은 순서로 나열한 것입니다.
Best-5 정도까지는 학습이 순조롭게 진행되고 있는 걸 확인할 수 있습니다. Best-1 ~ Best-5의 결과 중 학습이 잘 진행될 때의 학습률은 0.006~0.01, 가중치 감소 계수는 1e-8 ~ 1e-6 정도라는 걸 알 수 있습니다.
위의 과정을 통해 범위를 계속 좁혀나가면서 적절한 하파 값을 정하면 그것이 바로 하이퍼파라미터 최적값입니다.
다음 포스트에서는 합성곱 신경망인 CNN에 대해서 공부해보도록 하겠습니다!
2020/07/10 - [Computer Science/Deep Learning] - [비전공자용]합성곱 신경망 (CNN) - 합성곱 계층 & 풀링 계층
[비전공자용]합성곱 신경망 (CNN) - 합성곱 계층 & 풀링 계층
합성곱 신경망 Convolutional Neural Network, CNN은 이미지 인식과 음성 인식 등 다양한 곳에서 사용됩니다. 이제부터 CNN에 대해서 낱낱이 살펴보도록 합시다. # CNN 전체 구조 지금까지 공부했던 신경망��
huangdi.tistory.com
[출처] Deep Learning from Scratch, ゼロ から作る
'Computer Science > Deep Learning' 카테고리의 다른 글
[비전공자용] [Python] CNN(합성곱 신경망) - 합성곱 계층 구현 (2) | 2020.07.28 |
---|---|
[비전공자용]합성곱 신경망 (CNN) - 합성곱 계층 & 풀링 계층 (2) | 2020.07.10 |
[비전공자용] 오버피팅 Overfitting 억제법 - 1.가중치 감소 2.드롭아웃 Dropout (0) | 2020.07.10 |
[비전공자용] [Python] 배치 정규화 Batch Normalization (2) | 2020.07.10 |
[비전공자용] [Python] Xavier Initialization (Xavier 초기화) & He Initialization (He 초기화) (0) | 2020.07.10 |