시작에 앞서
해당 내용은 '<파이썬 머신러닝 완벽 가이드> 권철민 지음. 위키북스' 를 토대로 작성되었습니다. 보다 자세한 내용은 해당 서적에 상세히 나와있으니 서적을 참고해 주시기 바랍니다.
이전 내용
[파이썬] 분류 > 베이지안 최적화 (1)
시작에 앞서해당 내용은 ' 권철민 지음. 위키북스' 를 토대로 작성되었습니다. 보다 자세한 내용은 해당 서적에 상세히 나와있으니 서적을 참고해 주시기 바랍니다.베이지안 최적화 XGBoost나 Ligh
puppy-foot-it.tistory.com
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 |