728x90
하이퍼 파라미터 튜닝의 주요 이슈
- Gradient Boosting 기반 알고리즘은 튜닝해야 할 파라미터 개수가 많고 범위가 넓어서 가능한 개별 경우의 수가 너무 많음
- 이러한 경우 데어터가 크면, 하이퍼 파라미터 튜닝에 굉장히 오랜 시간이 투입되어야 함
GridSearchCV vs RandomSearchCV
- GridSearchCV는 수행 시간이 너무 오래 걸림. 모든 경우의 수를 다 수행해 보기 때문에 데이터 세트가 작을때 유리
- RandomizedSeachCV는 수행 시간은 줄여주지만, Random한 선택으로 최적 하이퍼 파라미터 검출에 제약이 있음(데이터 세트가 클 때 유리함)
- 두 방법 모두 Iteration 중에 어느정도 최적화된 하이퍼 파라미터들을 활용하면서 최적화를 수행할 수 없음
Bayesian Optimization
- 가능한 최소의 시도로 최적의 답을 찾아야 할 경우 사용
- 베이지안 최적화는 미지의 함수가 반환하는 값의 최소 또는 최대값을 만드는 최적해를 짧은 반복을 통해 찾아내는 최적화 방식
- 새로운 데이터를 입력 받았을 때, 최적 함수를 예측하는 사후 모델을 개선해 나가면서 최적 함수를 도출
- 대체 모델과 획득 함수로 구성
- 대체모델은 획득 함수로부터 최적 입력값을 추천 받은 뒤 이를 기반으로 최적 함수 모델을 개선
- 획득함수는 개선된 대체 모델을 기반으로 다시 최적 입력값을 계산
Bayesian Optimization를 구현한 주요 패키지
- HyperOpt
- Bayesian optimization
- Optuna
HyperOpt의 주요 구성 요소
HyperOpt를 XGBoost 하이퍼 파라미터 튜닝에 적용
1. 학습/검증/테스트 데이터 분류
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')
dataset = load_breast_cancer()
cancer_df = pd.DataFrame(data=data.data, columns=dataset.feature_names)
cancer_df['target'] = dataset.target
X_features = cancer_df.iloc[:,:-1]
y_label = cancer_df.iloc[:,-1]
# 전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출
X_train, X_test, y_train, y_test = train_test_split(X_features, y_label, test_size=0.2, random_state=156)
# 학습 데이터를 다시 학습과 검증 데이터로 분리
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.1, random_state=156)
2. search space 지정 (입력값 범위 지정)
from hyperopt import hp
# 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.qnuiform('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)
}
3. 목적함수
from sklearn.model_selection import cross_val_score
from xgboost import XGBClassifier
from hyperopt import STATUS_OK
# fmin()에서 입력된 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)
# accuracy는 cv=3 개수만큼의 정확도 결과를 가지므로 이를 평균해서 반환하되 -1을 곱해줌.
return {'loss':-1 * np.mean(accuracy), 'status': STATUS_OK}
4. 목적함수를 실행하여 최소 반환값 (loss)를 최적으로 찾아냄 fmin()
tpe는 Tree-structured Parzen Estimator의 약자
suggest는 하이퍼파라미터 최적화를 위한 알고리즘
이 알고리즘은 베이지안 최적화 방법 중 하나로, 기존에 수행된 시험(trial) 결과를 사용하여 하이퍼파라미터 공간을 탐색하고 더 나은 후보를 제안
하이퍼파라미터 최적화를 위해 tpe.suggest는 거의 고정적으로 쓰임
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)
5. XGBClassifier에 위에서 찾은 최적값을 적용후 학습/검증 데이터 학습하고 테스트 데이터로 예측값 반환
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
# 평가지표를 위한 함수 생성
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print 추가
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
#XGBClassifier로 학습/검증/예측
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=True)
preds = xgb_wrapper.predict(X_test)
pred_proba = xgb_wrapper.predict_proba(X_test)[:, 1]
get_clf_eval(y_test, preds, pred_proba)
728x90
'머신러닝' 카테고리의 다른 글
[분류] stacking (0) | 2024.03.07 |
---|---|
[분류] 신용카드 사기 검출 (1) | 2024.03.06 |
[분류] 부스팅 - XGBoost (0) | 2024.03.03 |
[분류] 앙상블 학습 - 보팅, 배깅, 부스팅 (0) | 2024.03.03 |
[분류] 랜덤포레스트 RandomForest (0) | 2024.03.03 |