Deep learning/이론(hands on machine learning)

8. 신경망 하이퍼파라미터 튜닝

jwjwvison 2021. 6. 2. 23:40

 어떻게 하면 어떤 하이퍼파라미터 조합이 주어진 문제에 최적인지 알 수 있을까?

 

 한 가지 방법은 많은 하이퍼파라미터 조합을 시도해보고 어떤 것이 검증 세트에서 (또는 K-폴드 교차 검증으로) 가장 좋은 점수를 내는지 확인하는 것이다. GrdiSearchCV나 RandomizedSearchCV를 사용해 하이퍼파라미터 공간을 탐색할 수 있다. 이렇게 하려면 케라스 모델을 사이킷런 추정기처럼 보이도록 바꾸어야 한다.

def build_model(n_hidden=1,n_neurons=30,learning_rate=3e-3,input_shape=[8]):
  model=keras.models.Sequential()
  model.add(keras.layers.InputLayer(input_shape=input_shape))
  for layer in range(n_hidden):
    model.add(keras.layers.Dense(n_neurons,activation='relu'))
  model.add(keras.layers.Dense(1))
  optimizer=keras.optimizers.SGD(lr=learning_rate)
  model.compile(loss='mse',optimizer=optimizer)
  return model

 

 build_model() 함수를 사용해 KerasRegressor 클래스의 객체를 만든다.

keras_reg=keras.wrappers.scikit_learn.KerasRegressor(build_model)

 KerasRegressor 객체는 build_model() 함수로 만들어진 케러스 모델을 감싸는 간단한 래퍼(wrapper)이다. 이제 일반적인 사이킷런 회귀 추정기처럼 이 객체를 사용할 수 있다. 다음 코드와 같이 fit() 메서드로 모델을 훈련하고 score() 메서드로 평가하고 predict() 메서드로 예측을 만들 수 있다.

keras_reg.fit(X_train,y_train,epochs=100,
              validation_data=(X_valid,y_valid),
              callbacks=[keras.callbacks.EarlyStopping(patience=10)])
mse_test=keras_reg.score(X_test,y_test)
y_pred=keras_reg.predict(X_new)

 fit() 메서드에 지정한 모든 매개변수는 케라스 모델로 전달된다. 사이킷런은 손실이 아니라 점수를 계산하기 때문에(즉, 높을수록 좋다) 출력 점수는 음수의 MSE이다.

 

 모델 하나를 훈련하고 평가하려는 것이 아니라 수백 개의 모델을 훈련하고 검증 세트에서 최상의 모델을 선택해야 한다. 하이퍼파라미터가 많으므로 그리드 탐색보다 랜덤 탐색을 사용하는 것이 좋다. 은닉층 개수, 뉴런 개수, 학습률을 사용해 하이퍼파라미터 탐색을 수행해보자.

from scipy.stats import reciprocal   #상호연속적인 랜던분포
from sklearn.model_selection import RandomizedSearchCV
import numpy as np

param_distribs={
    'n_hidden' : [0,1,2,3],
    'n_neurons' : np.arange(1,100),
    'learning_rate' : reciprocal(3e-4,3e-2)
}

rnd_search_cv=RandomizedSearchCV(keras_reg,param_distribs,n_iter=10,cv=3)
rnd_search_cv.fit(X_train,y_train,epochs=100,
                  validation_data=(X_valid,y_valid),
                  callbacks=[keras.callbacks.EarlyStopping(patience=10)])

 

1. 은닉층 개수

 복잡한 문제에서는 심층 신경망이 얕은 신경망보다 파라미터 효율성이 훨씬 좋다. 심층 신경망은 복잡한 함수를 모델링하는 데 얕은 신경망보다 훨씬 적은 수의 뉴런을 사용하므로 동일한 양의 훈련 데이터에서 더 높은 성능을 낼 수 있다.

 

2. 은닉층의 뉴런 개수

 입력층과 출력층의 뉴런 개수는 해당 작업에 필요한 입력과 출력의 형태에 따라 결정된다. 예를 들어 MNSIT는 28x28=784개의 입력 뉴런과 10개의 출력 뉴런이 필요하다. 대부분의 경우 모든 은닉층에 같은 크기를 사용해도 동일하거나 더 나은 성능을 낸다. 또한 튜닝할 하이퍼파라미터가 층마다 한 개씩이 아니라 전체를 통틀어 한 개가 된다. 데이터셋에 따라 다르지만 다른 은닉층보다 첫 번째 은닉층을 크게 하는 것이 도움이 된다.

 

 층의 개수와 마찬가지로 네트워크가 과대적합이 시작되기 전까지 점진적으로 뉴런 수를 늘릴 수 있다. 하지만 실전에서는 필요한 것보다 더 많은 층과 뉴런을 가진 모델을 선택하고, 그런 다음 과대적합되지 않도록 조기 종료나 규제 기법을 사용하는 것이 간단하고 효과적이다. 다른 한편으로는 한 층의 뉴런 수가 너무 적으면 입력에 있는 유용한 정보를 모두 유지하기 위한 충분한 표현 능력을 가지지 못한다.(예를 들어, 뉴런 두 개를 가진 층은 2D 데이터만 출력할 수 있다. 만약 3D 데이터를 처리한다면 일부 정보를 잃게 된다).