본문 바로가기
ㄴ 공부공부룸/AI

하이퍼파라미터 튜닝

by sPARKle_judy 2022. 12. 6.
728x90

[2022.12.06 모델 성능을 최적화하기 위한 하이퍼파라미터 튜닝 방법 searching]

 

1. Hyperparameter란?

모델링할 때 사용자가 직접 세팅해주는 값

정해진 최적의 값은 없고, 휴리스틱한 방법이나 rules of thumb에 의해 결정하는 경우가 대부분이고, bayesian optimization와 같은 자동으로 선택해주는 라이브러리를 사용하기도 한다.

 

 

그렇다면 parameter와의 차이점은?

사용자에 의해 직접 설정되는 지의 여부가 가장 큰 차이점

 

  hyperparameter parameter
설명 모델 학습 과정에 반영되는 값 모델 내부에서 결정되는 변수
특징 최적의 훈련 모델을 구현하기 위해
학습 시작 전에 미리 조정됨
데이터로부터 학습 또는 예측되며
훈련 모델의 성능은 파라미터에 의해 결정됨
예시 학습률, 손실함수, 배치사이즈 정규분포의 평균, 표준편차,
선형 회귀 계수,가중치, 편향
직접 조정 가능 가능 불가능

 

 


 

2. 하이퍼파라미터 튜닝이 필요한 이유

모든 데이터에는 그에 맞는 좋은 하이퍼파라미터가 존재한다. 

그래서 데이터마다 좋은 입력값을 설정해주어 가장 좋은 결과를 찾아야 하는데, 이를 하이퍼파라미터 튜닝이라고 한다.

즉, 하이퍼파라미터 튜닝은 모델을 최적화하기 위해 모델의 하이퍼파라미터를 조정하는 과정을 말한다.

 

 


 

3. 하이퍼파라미터 종류

종류 설명 특징
학습률
(learning rate)
손실 함수의 경사를 따라 이동하는 정도를 결정하는 변수  > 너무 낮으면 학습 속도가 늦고, 너무 높으면 경사 하강 과정에서 발산하면서 최적값을 찾을 수 없다.

 > 기본 학습률은 0.001로 설정되어 있다.
반복 학습 횟수
(training epochs)
학습 횟수를 결정하는 변수  > 학습 효율이 떨어지는 시점을 적절히 판단하여 조기종료를 설정해 overfitting을 방지한다.

 > 학습률을 조정하면 최적값에 도달할 수 있는 반복 학습 횟수 또한 변경되어, 학습률을 고려하여 튜닝해주는 것이 좋다.
손실 함수
(cost function)
입력에 따른 예측값과 실제값의
차이를 계산하는 함수
 > 손실이 작을수록 모델 성능이 좋다. 

 > 평균 제곱 오차(MSE; Mean Squared Error), Cross entropy 함수 등이 있다.
정규화 파라미터
(regularization
parameter)
error를 최소화하고 과적합
(overfitting)을 피하기 위해 L1 또는 L2 정규화 방법 사용
 > Batch normalization과는 엄연히 다른 개념이다.

 > L2 regularization이 더 보편화된 일반화 기법이다.

 > loss function에 L1, L2에서의 각각의 값을 더해 weight의 update 과정에서 보정값을 주는 것이다.
배치 사이즈
(batch size)
전체 학습 데이터를 나누는 크기를 결정하는 변수  > 가용 메모리 크기와 epoch 수행 성능을 고려하여 결정한다.

 > overfitting이 심한 경우 batch를 축소해야 한다.

 > 32~512 등 2의 제곱 배수로 진행한다.

 > batch size가 너무 작으면 학습 시간이 증가하고 노이즈 발생 가능성이 존재한다.

 > mini batch는 전체 dataset을 같은 크기로 나누었을 때 각
batch dataset의 크기이다.

 > Total dataset = Batch Size * mini batch
 > 1 epoch = Batch Size * Iteration
은닉층의 개수
(hidden unit)
train 데이터에 대한 학습 최적화를 결정하는 변수  > 은닉층의 수는 복잡도를 높이는 데에 영향을 주므로, 많을수록 성능이 올라갈 수 있지만, overfitting의 위험도 존재한다.

 > 보통 첫 hidden layer의 뉴런 수가 input layer보다 큰 것이 효과적이다.
기중치 초기화
(weight initialization)
학습 도중 vanishing gradient나
exploding gradient현상을
회피하기 위한 단계
 > 초기 가중치를 어떻게 설정할 지는 신경망에서 매우 중요하다.

 > sigmoid나 tanh를 활성화 함수로 주로 사용: Xavier 초기화
 > ReLU를 활성화 함수로 주로 사용: Kaining He 초기화
모멘텀
(momentum)
gradient descent에 대한
optimization기법으로.
weight에 관성을 주는 것
 > global minimum에 도달하기 위해 학습 과정에서 weight에 관성, 가속도를 주어 지역 최저점에 빠지지 않게 한다.

 > backpropagation에서 weight update에 사용되는 hebbian learning rule에서 chain rule의 결과값과 곱셈으로 추가하여 사용된다.

 

 


 

4. 하이퍼파라미터 튜닝 기법

크게 휴리스틱 방법과 자동으로 서칭해주는 방법으로 나뉜다.

  • Manual Search
  • Automated Hyper-Parameter Selection

 

 

1) Manual Search

; 휴리스틱 기반 방식, 탐색의 단순성

 

경험 또는 감으로 하이퍼파라미터 값을 설정하는 방법으로, 'rules of thumb' 이라고도 한다.

사용자의 직관과 경험 기반(휴리스틱 조합)으로 탐색하고 조합 중 최적 조합을 적용(탐색의 단순성 적용)한다.

 

한 마디로 노가다. 모델 돌릴 때마다 하이퍼파라미터 수정해서 이건 어떤가 저건 어떤가 확인해 보는 것.

그래서 하이퍼파라미터 조합 별 성능 비교가 어렵다.

 

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

...

manual = RandomForestClassifier(random_state= 101).fit(X_Train,Y_Train)
predictionforest = manual.predict(X_Test)
man1_acc = accuracy_score(Y_Test,predictionforest)

 

최적의 하이퍼파라미터 찾는 방법?

 

1. 정밀하고 랜덤하게 돌려보기

랜덤하게 점을 찍은 파라미터 값들로 모델을 돌리고, 가장 좋은 성능을 내는 점 주변에 더 좋은 성능을 낼 수 있는 점이 존재할 수 있기 때문에 그 주변 공간을 zoom-in 하여 랜덤하게 다시 점들을 찍어 모델을 돌려본다.

 

2. 적절한 척도 선택하기

선형척도로 무작위로 선택하면 위의 그림과 같이 0.1에서 1 사이에 점들이 몰려 찍혀 비합리적인 랜덤서치가 될 수 있다. 따라서 선형척도보다는 로그척도에서 랜덤하게 값을 찍어 더 합리적으로 랜덤서치를 한다.

 

 

 

2) Grid Search

; 모든 조합 탐색, 균등 탐색

 

가장 기본적인 하이퍼파라미터 최적화 방법으로, 'exhaustive searching' 이라고도 한다.

가능한 모든 조합의 하이퍼파라미터로 훈련시켜서 최적의 조합을 탐색한다. 따라서 하이퍼파라미터의 개수가 증가하면 전수 탐색에 한계가 있으며 시간 또한 오래 걸린다는 단점이 있다.

 

from sklearn.model_selection import GridSearchCV

...

# grid search 탐색 범위 정의
grid_search = {'criterion': ['entropy', 'gini'],
               'max_depth': [2],
               'max_features': ['auto', 'sqrt'],
               'min_samples_leaf': [4, 6, 8],
               'min_samples_split': [5, 7,10],
               'n_estimators': [20]}
               
clf = RandomForestClassifier()
grid = GridSearchCV(estimator = clf, param_grid = grid_search, 
                               cv = 4, verbose= 5, n_jobs = -1)
grid.fit(X_Train,Y_Train)

grid_pf = grid.best_estimator_.predict(X_Test)
grid_acc = accuracy_score(Y_Test,grid_pf)

 

 

 

3) Random Search

; 랜덤 샘플링, 최댓값-최솟값 부여

 

경계 내에서 임의의 조합을 추출하여 최적의 조합을 찾는 방법으로, grid search에 비해 시간 대비 성능이 좋다.

특정값이 정해지지 않은 탐색 범위 내에서 조합을 무작위로 추출하기 때문에 조합이 산발적으로 분포되어 있고, 시도 횟수는 사용자가 정해줄 수 있기 때문에 grid search에 비해 적은 횟수로 끝마칠 수 있다.

하지만 "랜덤"하게 몇 개만 뽑아서 확인해보는 방식이기에 정확도가 떨어질 수 있다는 단점이 있다.

 

from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score

random_search = { 'criterion': ['entropy', 'gini'],
               'max_depth': [2],
               'max_features': ['auto', 'sqrt'],
               'min_samples_leaf': [4, 6, 8],
               'min_samples_split': [5, 7,10],
               'n_estimators': [20] }

clf = RandomForestClassifier()
random = RandomizedSearchCV(estimator = clf, param_distributions = random_search, n_iter = 10, 
			    cv = 4, verbose= 1, random_state= 101, n_jobs = -1)
random.fit(X_Train,Y_Train)

random_pf = random.best_estimator_.predict(X_Test)
random_acc = accuracy_score(Y_Test,random_pf)

 

 

 

4) Bayesian Optimization

; 기존 추출 기반 탐색, bayesian theory

 

베이지안 최적화는 목적함수를 최대 또는 최소로 하는 최적해를 찾는 방법으로, 베이지안 정리를 활용한다.

 

베이지안 최적화에 나오는 개념 2가지

 

1. Surrogate model: 사전 정보를 학습하고 미지의 목적 함수 f의 형태에 대한 확률적인 추정을 하는 모델로, '하이퍼파라미터 집합''일반화 성능'의 관계를 모델링한다.

 

2. Acquisiton function: surrogate model이 확률적으로 추정한 결과를 바탕으로 다음 입력값 후보(하이퍼파라미터 조합)를 추천하는 함수

 

 

 

베이지안 최적화를 하는 과정은 다음과 같다.

 

먼저 목적함수와 하이퍼파라미터의 조합을 대상으로 surrogate model을 만들어 평가한다.

여기서 목적함수는 loss, accuracy 등 우리가 구하고자 하는 지표를 말한다.

 

 

 

이후 aquisition function을 사용하여 다음 입력값 후보를 추천하여 추가한다.

 

 

'새롭게 추가된 하이퍼파라미터 집합을 포함한 하이퍼파라미터 집합'과 '일반화 성능'의 관계를 다시 surrogate model을 통해 모델링한다.

 

 

이 과정을 반복하면서 업데이트하여 최적의 조합을 찾아낸다.

 

아래 그림은 베이지안 최적화의 전체적인 과정을 도식화한 것이다. 

 

- 검은색 점으로 표시된 observation: 각 step에서의 관찰
- 빨간색 점으로 표시된 new observation: 해당 step에서의 새로운 관찰
- 실선으로 표시된 posterior mean: surrogate model
- 점선으로 표시된 objective function: 학습을 통해 최적화시키려는 함수
- 보라색 범위: 오차
- 초록색 선으로 표시된 Acquisition function: 다음 입력값 후보들
- 빨간색 세모로 표시된 Acquisiton max: 다음 관찰 지점이 되는 곳

 

t=2 시점에서 관찰한 결과 빨간색 세모 지점에서 최댓값이 나왔다. 이 지점이 t=3 시점에서의 관찰지점이 되는 것이고 그 부근에 보라색 범위가 사라진 것으로 보아 불확실성이 사라졌다고 볼 수 있다. 그리고 새로운 최댓값이 등장하면서 관찰 지점이 옮겨간다.

 

이 과정을 반복하면서 예측값과 실제 함수값이 거의 유사해지는 순간까지 하이퍼파라미터 조합을 최적화한다.

 

from sklearn.metrics import make_scorer, roc_auc_score
from sklearn.model_selection import cross_validate
import lightgbm as lgb
from bayes_opt import BayesianOptimization

# 목적함수 생성
# 호출 시 실수형 값들이 들어올 수 있으므로 정수형 하이퍼파라미터는 정수형으로 변경해줘야 함

# 목적함수 예시: lightGBM
def lgbm_cv(learning_rate, num_leaves, max_depth, min_child_weight, colsample_bytree, 
            feature_fraction, bagging_fraction, lambda_l1, lambda_l2):
    model = lgb.LGBMClassifier(learning_rate=learning_rate,
                                n_estimators = 1000, #고정값
                                #boosting = 'dart',
                                num_leaves = int(round(num_leaves)),
                                max_depth = int(round(max_depth)),
                                min_child_weight = int(round(min_child_weight)),
                                colsample_bytree = colsample_bytree,
                                feature_fraction = max(min(feature_fraction, 1), 0),
                                bagging_fraction = max(min(bagging_fraction, 1), 0),
                                lambda_l1 = max(lambda_l1, 0),
                                lambda_l2 = max(lambda_l2, 0)
                               )
    scoring = {'roc_auc_score': make_scorer(roc_auc_score)}
    result = cross_validate(model, X, y, cv=5, scoring=scoring)
    auc_score = result["test_roc_auc_score"].mean()
    return auc_score
    
# 입력값의 탐색 대상 구간
bayes_params = {'learning_rate' : (0.01, 0.05),
           		'num_leaves': (300, 600),
           		'max_depth': (2, 25),
           		'min_child_weight': (30, 100),
           		'colsample_bytree': (0, 0.99),
           		'feature_fraction': (0.0001, 0.99),
           		'bagging_fraction': (0.0001, 0.99),
           		'lambda_l1' : (0, 0.99),
           		'lambda_l2' : (0, 0.99),
          		}
 
# f: 목적함수, pbounds:입력값의 탐색구간
bayes_model = BayesianOptimization(f=lgbm_cv, pbounds=bayes_params, verbose=2, random_state=42 )

# 목적함수가 최대가 되는 최적해 찾기(acq=ei)
# init_points: 처음 탐색 횟수, n_iter: 연산 횟수
bayes_model.maximize(init_points=5, n_iter=20, acq='ei', xi=0.01)

# 최종 도출된 최적해 확인
bayes_model.max

 

만약 데이터 수가 적고 모델이 가볍다면 init_points와 n_iter를 크게 설정하여 최적화하는 것이 좋다.

 

 

 

728x90
LIST

'ㄴ 공부공부룸 > AI' 카테고리의 다른 글

[위변조] CAT-Net  (0) 2023.01.13
[OCR] PixelLink  (0) 2022.12.06
[OCR] Text detection model research  (0) 2022.11.29