시작에 앞서
해당 내용은 '<파이썬 머신러닝 완벽 가이드> 권철민 지음. 위키북스' 를 토대로 작성되었습니다. 보다 자세한 내용은 해당 서적에 상세히 나와있으니 서적을 참고해 주시기 바랍니다.
이전 내용
HyperOpt를 이용한 XGBoost 하이퍼 파라미터 최적화
위스콘신 유방암 데이터 세트를 이용하여 HyperOpt를 이용한 XGBoost의 하이퍼 파라미터를 최적화를 수행해본다.
[HpyerOpt를 이용한 XGBoost 하이퍼 파라미터 최적화 방법]
- 적용해야 할 하이퍼 파라미터와 검색 공간 설정
- 목적 함수에서 XGBoost 학습 후 에측 성능 결과를 반환 값으로 설정
- fmin() 함수에서 목적 함수를 하이퍼 파라미터 검색 공간의 입력값들을 사용하여 최적의 예측 성능 결과를 반환하는 최적 입력값들을 결정
※ 단, HyperOpt는 입력값과 반환값이 모두 실수형이기 때문에 하이퍼 파라미터 입력 시 형변환을 해줘야 하고,
HpyerOpt 목적 함수는 최솟값을 반환할 수 있도록 최적화해야 하기 때문에 성능 값이 클수록 좋은 성능 지표일 경우 -1을 곱해줘야 한다.
# 위스콘신 유방암 예측 (HyperOpt 활용)
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
dataset = load_breast_cancer()
cancer_df = pd.DataFrame(data=dataset.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_train, y_train을 다시 쪼개 90% 학습, 10% 검증용 데이터 분리
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.1, random_state=156)
◆ 하이퍼 파라미터 검색 공간 설정
max_depth, min_child_weight는 정수형 하이퍼 파라미터 이므로 hp.quniform을,
learning_rate, colsample_bytree는 hp.uniform 사용
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.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)
}
◆ 목적 함수 설정
하이퍼 파라미터 튜닝을 위한 목적 함수는 검색 공간에서 설정한 하이퍼 파라미터들을 입력 받아서 XGBoost를 학습하고 평가지표를 반환할 수 있도록 구성.
[유의할 점]
- 검색 공간에서 목적 함수로 입력되는 모든 인자들은 실수형 값이므로 이들을 XGBoostClassifier의 정수형 하이퍼 파라미터값으로 설정할 때는 정수형으로 형변환을 해야 한다.
예. XGBoostClassifier(max_depth=int(search_space['max_depth']))
- HpyerOpt의 목적 함수는 최솟값을 반환할 수 있도록 최적화해야 하기 때문에 정확도와 값이 클수록 좋은 성능 지표일 경우 -1을 곱한 뒤 반환하여, 더 큰 성능 지표가 더 작은 반환값이 되도록 만들어줘야 한다.
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 개수만큼 roc-auc 결과를 리스트로 가짐. 이를 평균해서 반환하되 -1 곱합
return {'loss':-1 * np.mean(accuracy), 'status':STATUS_OK}
◆ fmin() 을 이용해 최적 하이퍼 파라미터 도출
최대 반복 횟수 max_evals 는 50,
앞서 설정한 목적 함수 objective_func, 검색 공간 xgb_search_space 등을 인자로 입력rstate는 np.random.default_rng(seed=9)) 로 설정
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)
▶ best 출력 결과
colsample_bytree가 0.54241, learning_rate가 0.12601, max_depth가 17.0, min_child_weight가 2.0 이 도출되었다.
여기서 정수형 파라미터인 max_depth, min_child_weight가 실수형 값으로 도출되었다.
◆ 최적 하이퍼 파라미터 변환
추출된 최적 하이퍼 파라미터를 직접 XGBClassifier에 인자로 입력하기 전에 정수형 하이퍼 파라미터는 정수형으로 형 변환을, 실수형 하이퍼 파라미터는 소수점 5자리까지만 변환
print('colsample_bytree:{0}, learning_rate:{1}, max_depth:{2}, min_child_weight:{3}'.format(round(best['colsample_bytree'], 5),
round(best['learning_rate'], 5),
int(best['max_depth']),
int(best['min_child_weight'])))
◆ 성능 평가 확인
도출된 최적 하이퍼 파라미터들을 이용해서 XGBClassifier를 재학습한 후 성능 평가 결과를 확인
XGBoost의 조기 중단을 검증 데이터 세트로 활용하며 n_estimators는 400으로 증가시키고,
앞서 사용되었던 clf_get_eval( ) 을 이용.
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix
from sklearn.metrics import f1_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)
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))
xgb_wrapper = XGBClassifier(n_estiamtors=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)
'[파이썬 Projects] > <파이썬 머신러닝>' 카테고리의 다른 글
[머신러닝] 분류 - 캐글 신용카드 사기 검출 (0) | 2024.07.08 |
---|---|
[머신러닝] 분류 - 캐글 산탄데르 고객 만족 예측 (0) | 2024.07.07 |
[머신러닝] 분류 - 베이지안 최적화 (1) (0) | 2024.07.07 |
[머신러닝] 앙상블 : LightGBM (0) | 2024.07.04 |
[머신러닝] 앙상블 : XG Boost (3) (0) | 2024.07.04 |