HyperOpt를 이용한 XGBoost 하이퍼 파라미터 튜닝
HyperOpt를 이용하여 XGBoost 하이퍼 파라미터를 최적화 해본다. 주의사항은 다음과 같다.
- HyperOpt는 입력값과 반환값이 모두 실수형이기 때문에 정수형 하이퍼 파라미터 입력 시 형변환 필요
 - HyperOpt의 목적 함수는 최소값을 반환할 수 있도록 최적화하기 때문에 성능 값이 클수록 좋은 성능 지표일 경우 -1을 곱해주어야 함(분류는 성능 값이 클수록 좋기때문에 -1을 곱해주고, 회귀는 성능 값이 작을수록 좋기 때문에 -1을 곱하지 않고 그대로 사용)
 
○필요한 패키지 및 모듈 불러오기
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
○데이터 로드
# 유방암 데이터셋 
dataset = load_breast_cancer()
cancer_df = pd.DataFrame(data=dataset.data, columns=dataset.feature_names)
cancer_df['target'] = dataset.target
cancer_df.head()
○데이터 분리
# 피처와 타겟 분리
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)
# 학습 데이터를 다시 학습과 검증 데이터로 분리(학습:9 / 검증:1)
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.1, random_state=156)
○모델 성능 평가 함수 선언
from sklearn.metrics import *
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_score(y_test, pred_proba)
    
    print('오차 행렬')
    print(confusion)
    print('정확도:{0:.4f}, 정밀도:{1:.4f}, 재현율:{2:.4f}, F1:{3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
○HyperOpt 설정 1 - 검색 공간 설정
- 하이퍼 파라미터 검색 공간 설정(정수형 하이퍼 파라미터 → hp.quniform() 사용)
 
# HyperOpt 검색 공간 설정
from hyperopt import hp
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)}
○HyperOpt 설정 2 - 목적 함수 설정
- 검색 공간에서 설정한 하이퍼 파라미터들을 입력받아서 XGBoost를 학습하고, 평가 지표를 반환하도록 구성
 
한 가지 아쉬운 점은 XGBoost, LightGBM에서는 cross_val_score() 적용할 경우 조기 중단(early stopping)이 지원되지 않음. 따라서 조기 중단을 하기 위해서 KFold로 학습과 검증용 데이터 세트를 만들어서 직접 교차검증을 수행해야 함
# HyperOpt 목적 함수 설정
from sklearn.model_selection import cross_val_score # 교차검증
from xgboost import XGBClassifier
from hyperopt import STATUS_OK
def objective_func(search_space):
    xgb_clf = XGBClassifier(
        n_estimators=100,
        max_depth=int(search_space['max_depth']), # 정수형 하이퍼 파라미터 형변환 필요:int형
        min_child_weight=int(search_space['min_child_weight']), # 정수형 하이퍼 파라미터 형변환 필요:int형
        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}
○HyperOpt 설정 3 - fmin()을 이용해 최적 하이퍼 파라미터 도출
# HyperOpt fmin()을 이용해 최적 하이퍼 파라미터 도출
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)

정수형 하이퍼 파라미터(max_depth, min_child_weight) 값이 실수형으로 도출됨을 유의하기
○추출된 최적 하이퍼 파라미터를 이용하여 XGBoost의 인자로 입력하여 학습 및 평가
- 입력하기 전에 정수형 하이퍼 파라미터 형변환 필수
 
# 도출된 최적 하이퍼 파라미터를 이용하여 모델 선언
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)
                           )
# 모델 학습: 조기 중단(early stopping) - 50
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)
# 예측
preds = xgb_wrapper.predict(X_test)
pred_proba = xgb_wrapper.predict_proba(X_test)[:, 1]
# 모델 평가
get_clf_eval(y_test, preds, pred_proba)
[0]	validation_0-logloss:0.56908	validation_1-logloss:0.60656
[1]	validation_0-logloss:0.47637	validation_1-logloss:0.53729
[2]	validation_0-logloss:0.40361	validation_1-logloss:0.48320
... ... ...
[130]	validation_0-logloss:0.01499	validation_1-logloss:0.24451
[131]	validation_0-logloss:0.01494	validation_1-logloss:0.24374
[132]	validation_0-logloss:0.01490	validation_1-logloss:0.24530
... ... ...
[179]	validation_0-logloss:0.01335	validation_1-logloss:0.24535
[180]	validation_0-logloss:0.01332	validation_1-logloss:0.24475
[181]	validation_0-logloss:0.01330	validation_1-logloss:0.24549
오차 행렬
[[34  3]
 [ 2 75]]
정확도:0.9561, 정밀도:0.9615, 재현율:0.9740, F1:0.9677, AUC:0.9933
'파이썬 머신러닝 완벽가이드 > [4장] 분류' 카테고리의 다른 글
| 캐글 신용카드 사기 검출(log 변환, 이상치 제거, SMOTE 오버샘플링 기초지식) (0) | 2023.02.24 | 
|---|---|
| 캐글 산탄데르 고객 만족 예측 (0) | 2023.02.23 | 
| 베이지안 최적화 기반의 HyperOpt를 이용한 하이퍼 파라미터 튜닝(1) (0) | 2023.02.20 | 
| LightGBM (0) | 2023.02.19 | 
| 부스팅 정리 (0) | 2023.02.15 |