인프런 커뮤니티 질문&답변
Bayesian Opt 관련 질문
작성
·
595
0
auc score 에 초점을 맞춰서인지 f1 score를 측정해보니,
거의 0에 가까운 값이 되었습니다. ㅠ
실제로는 못쓰는 모델이겠죠?
캐글에 제출해보려 했는데 캐글이 제공해주는 test data에 대해서 4개 빼고 전부 0이라 예측하더라구요 ㅜ
퀴즈
결정 트리(Decision Tree) 모델이 데이터를 분할(Split)할 때 사용하는 주요 기준 지표로 가장 적절한 것은 무엇일까요?
평균 제곱 오차 (Mean Squared Error)
정보 이득 (Information Gain) 또는 지니 계수 (Gini Coefficient)
회귀 계수 (Regression Coefficient)
주성분 (Principal Component)
답변 7
0
0
이 데이터 세트는 특성이 고객 불만족이 데이터가 극히 일부분인 imbalanced 데이터세트라 고객 불만족 데이터를 잘 맞추지 못할 경우 recall이 굉장히 저조해 지는 군요. recall이 저조해서 f1 score가 잘 나오지 않습니다.
이 경우는 hyper parameter tuning을 recall 또는 f1 score에 맞춰야 할 것 같습니다. bayesian optimization도 f1 score로 변경해야 될 것 같습니다.
0
0
### 데이터 전처리
!pip install bayesian-optimization
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
cust_df = pd.read_csv(r"C:\Users\user\Desktop\datasets\santander-customer-satisfaction/train.csv",encoding='latin-1')
print('dataset shape:', cust_df.shape)
cust_df.head(3)
cust_df.info()
print(cust_df['TARGET'].value_counts())
unsatisfied_cnt = cust_df[cust_df['TARGET'] == 1]['TARGET'].count()
total_cnt = cust_df['TARGET'].count()
print('unsatisfied 비율은 {0:.2f}'.format((unsatisfied_cnt / total_cnt)))
cust_df.describe( )
print(cust_df['var3'].value_counts( )[:10])
# var3 피처 값 대체 및 ID 피처 드롭
cust_df['var3'].replace(-999999, 2, inplace=True)
cust_df.drop('ID',axis=1 , inplace=True)
# 피처 세트와 레이블 세트분리. 레이블 컬럼은 DataFrame의 맨 마지막에 위치해 컬럼 위치 -1로 분리
X_features = cust_df.iloc[:, :-1]
y_labels = cust_df.iloc[:, -1]
print('피처 데이터 shape:{0}'.format(X_features.shape))
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_features, y_labels,
test_size=0.2, random_state=0)
train_cnt = y_train.count()
test_cnt = y_test.count()
print('학습 세트 Shape:{0}, 테스트 세트 Shape:{1}'.format(X_train.shape , X_test.shape))
print(' 학습 세트 레이블 값 분포 비율')
print(y_train.value_counts()/train_cnt)
print('\n 테스트 세트 레이블 값 분포 비율')
print(y_test.value_counts()/test_cnt)
from xgboost import XGBClassifier
from sklearn.metrics import roc_auc_score
# n_estimators는 500으로, random state는 예제 수행 시마다 동일 예측 결과를 위해 설정.
xgb_clf = XGBClassifier(n_estimators=500, random_state=156)
# 성능 평가 지표를 auc로, 조기 중단 파라미터는 100으로 설정하고 학습 수행.
xgb_clf.fit(X_train, y_train, early_stopping_rounds=100,
eval_metric="auc", eval_set=[(X_train, y_train), (X_test, y_test)])
xgb_roc_score = roc_auc_score(y_test, xgb_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(xgb_roc_score))
from sklearn.model_selection import GridSearchCV
# 하이퍼 파라미터 테스트의 수행 속도를 향상시키기 위해 n_estimators를 100으로 감소
xgb_clf = XGBClassifier(n_estimators=100)
params = {'max_depth':[5, 7] , 'min_child_weight':[1,3] ,'colsample_bytree':[0.5, 0.75] }
# 하이퍼 파라미터 테스트의 수행속도를 향상 시키기 위해 cv 를 지정하지 않음.
gridcv = GridSearchCV(xgb_clf, param_grid=params)
gridcv.fit(X_train, y_train, early_stopping_rounds=30, eval_metric="auc",
eval_set=[(X_train, y_train), (X_test, y_test)])
print('GridSearchCV 최적 파라미터:',gridcv.best_params_)
xgb_roc_score = roc_auc_score(y_test, gridcv.predict_proba(X_test)[:,1], average='macro')
print('ROC AUC: {0:.4f}'.format(xgb_roc_score))
# n_estimators는 1000으로 증가시키고, learning_rate=0.02로 감소, reg_alpha=0.03으로 추가함.
xgb_clf = XGBClassifier(n_estimators=1000, random_state=156, learning_rate=0.02, max_depth=5,\
min_child_weight=1, colsample_bytree=0.75, reg_alpha=0.03)
# evaluation metric을 auc로, early stopping은 200 으로 설정하고 학습 수행.
xgb_clf.fit(X_train, y_train, early_stopping_rounds=200,
eval_metric="auc",eval_set=[(X_train, y_train), (X_test, y_test)])
xgb_roc_score = roc_auc_score(y_test, xgb_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(xgb_roc_score))
# n_estimators는 1000으로 증가시키고, learning_rate=0.02로 감소, reg_alpha=0.03으로 추가함.
xgb_clf = XGBClassifier(n_estimators=1000, random_state=156, learning_rate=0.02, max_depth=7,\
min_child_weight=1, colsample_bytree=0.75, reg_alpha=0.03)
# evaluation metric을 auc로, early stopping은 200 으로 설정하고 학습 수행.
xgb_clf.fit(X_train, y_train, early_stopping_rounds=200,
eval_metric="auc",eval_set=[(X_train, y_train), (X_test, y_test)])
xgb_roc_score = roc_auc_score(y_test, xgb_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(xgb_roc_score))
from xgboost import plot_importance
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(1,1,figsize=(10,8))
plot_importance(xgb_clf, ax=ax , max_num_features=20,height=0.4)
### LightGBM 모델 학습과 하이퍼 파라미터 튜닝
from lightgbm import LGBMClassifier
lgbm_clf = LGBMClassifier(n_estimators=500)
evals = [(X_test, y_test)]
lgbm_clf.fit(X_train, y_train, early_stopping_rounds=100, eval_metric="auc", eval_set=evals,
verbose=True)
lgbm_roc_score = roc_auc_score(y_test, lgbm_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(lgbm_roc_score))
from sklearn.metrics import f1_score
f1_score(y_test, lgbm_clf.predict(X_test))
from sklearn.model_selection import GridSearchCV
# 하이퍼 파라미터 테스트의 수행 속도를 향상시키기 위해 n_estimators를 100으로 감소
LGBM_clf = LGBMClassifier(n_estimators=200)
params = {'num_leaves': [32, 64 ],
'max_depth':[128, 160],
'min_child_samples':[60, 100],
'subsample':[0.8, 1]}
# 하이퍼 파라미터 테스트의 수행속도를 향상 시키기 위해 cv 를 지정하지 않습니다.
gridcv = GridSearchCV(lgbm_clf, param_grid=params)
gridcv.fit(X_train, y_train, early_stopping_rounds=30, eval_metric="auc",
eval_set=[(X_train, y_train), (X_test, y_test)])
print('GridSearchCV 최적 파라미터:', gridcv.best_params_)
lgbm_roc_score = roc_auc_score(y_test, gridcv.predict_proba(X_test)[:,1], average='macro')
print('ROC AUC: {0:.4f}'.format(lgbm_roc_score))
lgbm_clf = LGBMClassifier(n_estimators=1000, num_leaves=32, sumbsample=0.8, min_child_samples=100,
max_depth=128)
evals = [(X_test, y_test)]
lgbm_clf.fit(X_train, y_train, early_stopping_rounds=100, eval_metric="auc", eval_set=evals,
verbose=True)
lgbm_roc_score = roc_auc_score(y_test, lgbm_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(lgbm_roc_score))
### BaysianOptimization을 이용한 하이퍼 파라미터 튜닝
하이퍼 파라미터 튜닝 대상을 Dictionary 형태로 정의합니다. 이때 개별 하이퍼 파라미터는 튜플형태의 범위값으로 주어집니다.
예를 들어 num_leaves의 값을 24~45 사이의 값을 입력하려면 'num_leaves':(24, 45)로 부여해야 합니다.
이 때 유의해야 할 사항은 num_leaves는 정수형값만 가능한 하이퍼 파라미터임에도 불구하고 BaysianOptimization 클래스가 해당 파라미터의 범위값을 입력 받으면 이를 무조건 정수형이 아닌 실수형 값으로
인식하여 값을 추출하는 것입니다. 즉 24.5, 25.4, 30.2, 27.2 와 같이 실수형 값을 num_leaves 값으로 설정하려고 시도하는데, 이는 실행 오류를 발생 시킵니다.
이러한 실행 오류를 막기 위해서는 호출되는 BayesianOptimization 평가 함수내에서 XGBoost/LightGBM의 하이퍼 파라미터를 다시 정수형 값으로 변경하면 됩니다. 이에 대해서는 다시 뒤에서 언급하도록 하겠습니다.
bayes_params = {
'num_leaves': (24, 45),
'colsample_bytree':(0.5, 1),
'subsample': (0.5, 1),
'max_depth': (4, 12),
'reg_alpha': (0, 0.5),
'reg_lambda': (0, 0.5),
'min_split_gain': (0.001, 0.1),
'min_child_weight':(5, 50)
}
테스트 해볼 하이퍼 파라미터의 범위 값을 설정하였으면 BaysianOptimization에서 호출하여 모델을 최적화하는 함수를 만들어 보겠습니다.
해당 함수는 BaysianOptimization에서 하이퍼 파라미터를 튜닝하기 위해 호출되면 제대로 튜닝이 되고 있는지를 판단하기 위해서 모델을 학습/평가하고 이에 따른 평가 지표를 반환하는 형식으로 만들어집니다. 이 평가 함수는 BayesianOptimization 객체에서 파라미터를 변경하면서 호출되므로 함수의 인자로 앞에서 딕셔너리로 설정된 파라미터들을 가지게 됩니다.
from lightgbm import LGBMClassifier
from sklearn.metrics import roc_auc_score
def lgb_roc_eval(num_leaves, colsample_bytree, subsample, max_depth, reg_alpha, reg_lambda, min_split_gain, min_child_weight):
params = {
"n_estimator":200,
"learning_rate":0.02,
'num_leaves': int(round(num_leaves)),
'colsample_bytree': colsample_bytree,
'subsample': subsample,
'max_depth': int(round(max_depth)),
'reg_alpha': reg_alpha,
'reg_lambda': reg_lambda,
'min_split_gain': min_split_gain,
'min_child_weight': min_child_weight,
'verbosity': -1
}
print("params:", params)
lgb_model = LGBMClassifier(**params)
lgb_model.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=30, eval_metric="auc", verbose=False )
best_iter = lgb_model.best_iteration_
print('best_iter:', best_iter)
valid_proba = lgb_model.predict_proba(X_test, num_iteration=best_iter)[:, 1]
roc_preds = roc_auc_score(y_test, valid_proba)
print('roc_auc:', roc_preds)
return roc_preds
BayesianOptimization 객체를 생성합니다.
이때 생성 인자로 앞에서 만든 평가함수 lgb_roc_eval 함수와 튜닝할 하이퍼 파라미터의 범위값을 설정한 딕셔너리 변수인 bayes_params를 입력합니다.
from bayes_opt import BayesianOptimization
BO_lgb = BayesianOptimization(lgb_roc_eval, bayes_params, random_state=0)
이제 입력받은 평가함수에 튜닝할 하이퍼 파라미터의 값을 반복적으로 입력하여 최적 하이퍼 파라미터를 튜닝할 준비가 되었습니다.
BayesianOptimization객체에서 maximize()메소드를 호출하면 이를 수행할 수 있습니다.
BO_lgb.maximize(init_points=5, n_iter=10)
BayesianOptimization 객체의 res 속성은 하이퍼 파라미터 튜닝을 하는 과정에서의 metric 값과 그때의 하이퍼 파라미터 값을 가지고 있음.
BO_lgb.res
BayesianOptimization 객체의 max 속성은 최고 높은 성능 Metric를 가질때의 하이퍼 파라미터 값을 가지고 있음.
BO_lgb.max
max_params = BO_lgb.max['params']
max_params['num_leaves'] = int(round(max_params['num_leaves']))
max_params['max_depth'] = int(round(max_params['max_depth']))
lgbm_clf = LGBMClassifier(n_estimators=1000, learning_rate=0.02, **max_params)
evals = [(X_test, y_test)]
lgbm_clf.fit(X_train, y_train, early_stopping_rounds=100, eval_metric="auc", eval_set=evals,
verbose=True)
lgbm_roc_score = roc_auc_score(y_test, lgbm_clf.predict_proba(X_test)[:,1],average='macro')
print('ROC AUC: {0:.4f}'.format(lgbm_roc_score))
p = lgbm_clf.predict(X_test)
from sklearn.metrics import f1_score
f1_score(y_test, p)
test_df = pd.read_csv(r'C:\Users\user\Desktop\datasets\santander-customer-satisfaction\test.csv',
encoding = 'latin-1')
test_df['var3'].replace(-999999, 2, inplace=True)
test_df.drop('ID',axis=1 , inplace=True)
testp = lgbm_clf.predict(test_df)
testp_df = pd.Series(testp)
testp_df.value_counts()0
0
하지만 강사님이 깃허브에 올려주신 bayesian opt 코드를 그대로 돌려도 f1_score 가 매우 낮게 나오네요 ㅜ
roc_auc_score 가 높으면 f1_score 가 높아야하는게 일반적인 것으로 알고 있는데, 다른 데이터에 이것저것 적용헤볼 경우에도 이런 사례가 간혹 있었네요 ㅜㅜ
어떤 문제인지 파악이 어려워 질문드립니다.
0





