반응형
Index
● 베이지안 최적화 개요
- GridSearch 와 같은 방식의 파라미터 튜닝은, 모든 조합의 수를 다해보기 때문에 computational cost가 매우 크다.
- 따라서 데이터 사이즈가 크거나, XGB, LightGBM 과 같이 느린 모델에는 베이지안 최적화기법이 선호된다.
- 베이지안 최적화란 ? "목적함수의 식을 모를 때 최대/최소 y값(f(x))을 반환하는 x를 찾는 기법" 이다.
- 베이지안 최적화의 중요한 두가지 요소는 대체모델(Surrogate Model)과 획득함수(Acquisition Function)이다.
- 대체모델(Surrogate Model)은 미지의 목적함수를 확률적으로 추정하는 모델로, 획득함수가 계산한 입력값(하이퍼 파라미터)기반으로 모델(최적함수)를 개선해 나간다. 아래 그림에서 파랑색 음영이 줄어들며 실선이 점선(목적함수)에 가까워 져가도록 하는것이 대체 모델(실선)이다.
- 획득함수(Acquisition Function)는 대체모델이 제시한 모델과, 이전 단계에서의 최적 관측값(가장큰값) 보다 더 큰 최대값을 가질것으로 기대되는 파라미터로 전달하고, 이를통해 대체모델은 모델을 개선해나간다. (파란음영이 좁아지고, 실선이 점선에 가까워진다)
● HyperOpt 사용하기
HyperOpt 는 베이지안 최적화를 구현한 파이썬 패키지이다. 아래 3개 단계를 따라 사용된다.
1. 입력변수와 검색공간 설정
입력변수의 검색공간을 제공하는 함수는 quniform 외에도 정규분포, 로그정규 등 다양한 함수 사용가능
from hyperopt import hp
# 1. 입력변수와 공간 설정
# -10 ~ 10까지 1간격을 가지는 입력 변수 x와 -15 ~ 15까지 1간격으로 입력 변수 y 설정.
search_space = {'x': hp.quniform('x', -10, 10, 1), 'y': hp.quniform('y', -15, 15, 1) }
2. 목적함수 설정(생성)
# 2. 목적합수 설정
# 목적 함수를 생성. 변숫값과 변수 검색 공간을 가지는 딕셔너리를 인자로 받고, 특정 값을 반환
def objective_func(search_space):
x = search_space['x']
y = search_space['y']
retval = x**2 - 20*y
return retval
3. 목적함수의 반환 최소값을 가지는 최적 입력값 유추
# 3. 목적함수의 반환 최솟값을 가지는 최적 입력값 유추
from hyperopt import fmin, tpe, Trials
# 입력 결괏값을 저장한 Trials 객체값 생성.
trial_val = Trials()
# 목적 함수의 최솟값을 반환하는 최적 입력 변숫값을 5번의 입력값 시도(max_evals=5)로 찾아냄. 랜덤시드 부분은 무시
best_01 = fmin(fn=objective_func, space=search_space, algo=tpe.suggest, max_evals=5
, trials=trial_val, rstate=np.random.default_rng(seed=0))
print('best:', best_01) # 반환예시: best: {'x': 1.0, 'y': -3.0}
# print(trial_val.results) trial 마다의 결과값 반환
# print(trial_val.vals) trial 마다의 입력값 반환
import pandas as pd
losses = [loss_dict['loss'] for loss_dict in trial_val.results]
result_df = pd.DataFrame({'x':trial_val.vals['x'], 'y':trial_val.vals['y'], 'losses':losses})
result_df.head(3)
● HyperOpt 사용한 하이퍼 파라미터 최적화 예시 (XGBoost)
from hyperopt import hp
# 1. 입력변수와 공간설정
# 정수형 파라미터는 정수형에 맞는 검색공간 설정 함수를 사용하고, 반환이후에도 int 함수로 변환해주는게 중요함
# max_depth는 5에서 20까지 1간격으로, min_child_weight는 1에서 2까지 1간격으로
# colsample_bytree는 0.5에서 1사이, learning_rate는 0.01에서 0.2 사이 정규 분포된 값으로 검색.
xgb_search_space = {'max_depth': hp.quniform('max_depth', 5, 20, 1),
'min_child_weight': hp.quniform('min_child_weight', 1, 2, 1),
'learning_rate': hp.uniform('learning_rate', 0.01, 0.2),
'colsample_bytree': hp.uniform('colsample_bytree', 0.5, 1),
}
# 2. 목적함수 설정 (정확도*-1 를 반환값으로 하는 함수)
from sklearn.model_selection import cross_val_score
from xgboost import XGBClassifier
from hyperopt import STATUS_OK
# search_space 값으로 입력된 모든 값은 실수형임.
# XGBClassifier의 정수형 하이퍼 파라미터는 정수형 변환을 해줘야 함.
# 정확도는 높을수록 더 좋은 수치임. -1 * 정확도를 곱해서 큰 정확도 값일수록 최소가 되도록 변환
def objective_func(search_space):
# 수행 시간 절약을 위해 n_estimators는 100으로 축소
xgb_clf = XGBClassifier(n_estimators=100, max_depth=int(search_space['max_depth']),
min_child_weight=int(search_space['min_child_weight']),
learning_rate=search_space['learning_rate'],
colsample_bytree=search_space['colsample_bytree'],
eval_metric='logloss')
accuracy = cross_val_score(xgb_clf, X_train, y_train, scoring='accuracy', cv=3)
# cross_val_score API 를 XGBoost 나 LightGBM 에 사용할떄는 early stopping 기능 지원안함
# accuracy는 cv=3 개수만큼 결과를 리스트로 가짐. 이를 평균해서 반환하되 -1을 곱함.
return {'loss':-1 * np.mean(accuracy), 'status': STATUS_OK}
# 최적의 파라미터 도출
from hyperopt import fmin, tpe, Trials
trial_val = Trials()
best = fmin(fn=objective_func,
space=xgb_search_space,
algo=tpe.suggest,
max_evals=50, # 최대 반복 횟수를 지정합니다.
trials=trial_val, rstate=np.random.default_rng(seed=9))
print('best:', best)
xgb_wrapper = XGBClassifier(n_estimators=400,
learning_rate=round(best['learning_rate'], 5),
max_depth=int(best['max_depth']),
min_child_weight=int(best['min_child_weight']),
colsample_bytree=round(best['colsample_bytree'], 5)
)
evals = [(X_tr, y_tr), (X_val, y_val)]
xgb_wrapper.fit(X_tr, y_tr, early_stopping_rounds=50, eval_metric='logloss',
eval_set=evals, verbose=False)
preds = xgb_wrapper.predict(X_test)
반응형
'Study > ML' 카테고리의 다른 글
10. 회귀(Regression) - 로지스틱 회귀, 회귀 트리 (0) | 2023.05.31 |
---|---|
9. 회귀(Regression) - 선형회귀 (0) | 2023.05.31 |
지니계수 (0) | 2023.05.28 |
7. 앙상블(Ensemble) - 부스팅(Boosting) (0) | 2023.05.28 |
6. 앙상블(Ensemble) - 보팅(Voting),배깅(Bagging) (0) | 2023.05.28 |
댓글