PL/Python

Ensemble Learning 6: XGBM python native

PIYA 2022. 12. 26.

Introduction

지난번에 XGBM의 이론적인 부분들에 대해서 포스팅했다.

너무 길어서 한번 자르고, 이번에는 실제 코드를 써보는 걸 정리해보자!

결국 이론만 알아서는 금방 잊기 쉽기때문에 꼭 코드로 실습해봐야한다.

 

dlmc 개발그룹에서 XGBoost를 개발하고 있는데,

처음엔 C/C++이었다가, R과 파이썬에서도 사용할 수 있게 호환되었다가,

이후 사이킷런이 흥하면서 사이킷런 wrapper용으로도 XGBoost를 확장했다.

 

이번엔 사이킷런이 아닌 파이썬 native 코드를 실습해보자!

 

 

실습 코드

유방암 데이터세트->DMatrix 변환

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import xgboost as xgb
from xgboost import plot_importance

# 유방암 데이터세트 로드 및 데이터프레임으로 변환
cancer = load_breast_cancer()
df = pd.DataFrame(data = cancer.data, columns = cancer.feature_names)
df['target'] = cancer.target

# 전체의 80%는 학습, 20%는 테스트셋으로 분리
X_train, X_test, y_train, y_test = train_test_split(df.iloc[:,:-1], df.iloc[:,-1], test_size=0.2)
# 80%인 학습을 또다시 9:1로 나눠 검증셋을 만든다.
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.1)

print(X_train.shape , X_test.shape)
print(X_tr.shape, X_val.shape)

# xgboost에 사용하기 위해 DMatrix로 변환한다.
dtr = xgb.DMatrix(data=X_tr, label=y_tr)
dval = xgb.DMatrix(data=X_val, label=y_val)
dtest = xgb.DMatrix(data=X_test, label=y_test)

데이터셋이 잘 나누어졌는지 확인

 

데이터셋으로는 위스콘신 유방암 데이터셋을 사용했다.

train_test_split()을 두 번 사용하여, 80:20으로 나누고 학습데이터를 다시 90:10으로 나누었다.

이후 데이터셋 수를 확인하고 DMatrix로 변환하였다.

 

 

 

하이퍼파라미터 세팅과 학습 과정

# 하이퍼파라미터 설정
params = { 'max_depth':3,
           'eta': 0.05, # learning rate
           'objective':'binary:logistic', # 목적함수: 이진분류
           'eval_metric':'logloss' # 로그 로스
}
num_rounds = 400

# 학습 데이터 셋은 'train' 또는 평가 데이터 셋은 'eval' 로 명기합니다.
# 또는 eval_list = [(dval,'eval')] 만 명기해도 무방.
eval_list = [(dtr, 'train'), (dval, 'eval')]

# 하이퍼파라미터와 early stopping 파라미터를 train() 함수의 파라미터로 전달
xgb_model = xgb.train(params=params, \
                      dtrain=dtr, \
                      num_boost_round=num_rounds, \
                      early_stopping_rounds=50, \
                      evals=eval_list)
# early_stopping_rounds: N번동안 eval-logloss가 더 줄지 않는다면 조기종료
# num_boost_round = 총 N번 돌려라

위의 코드를 보자.

사이킷런과 다르게 하이퍼파라미터들을 딕셔너리 형태로 잡아준 후,

xgb.train() 함수 호출시에 params에 넣어준다.

검증 데이터셋 또한 evals 파라미터에 전달한다.

또한 train() 메소드 호출 시 모델 객체를 반환받는다는 점에 유의하자.

 

early_stopping_rounds=50의 의미는

검증 데이터셋의 에러 eval-logloss가 50번 반복횟수동안 개선되지 않으면 학습을 조기 종료한다는 뜻이다.

 

예를들어 early_stopping_rouns=50일 때, 100번 iteration에서 early stopping이 일어났다면

50번째 eval-logloss가 최소값이고 그후 50번동안 eval-logloss가 개선되지 않았음을 의미한다.

 

 

 

예측 결과값 받기

import numpy as np

pred_probs = xgb_model.predict(dtest)
print('predict() 수행 결과값을 10개만 표시, 예측 확률 값으로 표시됨')
print(np.round(pred_probs[:10],3), '\n')

# 예측 확률이 0.5보다 크면 1, 그렇지 않으면 0으로 예측값 결정
preds = [1 if x>0.5 else 0 for x in pred_probs]
print('예측값 10개만 표시:', preds[:10])

Python native xgboost의 predict()는 사이킷런의 predict_proba()와 같이 동작한다.

따라서 위의 작업을 수행했다.

 

 

 

예측결과 평가하기

from sklearn.metrics import confusion_matrix, \
accuracy_score, precision_score, recall_score, 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_score(y_test, pred_proba)
    
    print('오차행렬')
    print(confusion, '\n')
    print('accuracy:', np.round(accuracy,3))
    print('precision:', np.round(precision,3))
    print('recall:', np.round(recall,3))
    print('F1:', np.round(f1,3))
    print('AUC:', np.round(roc_auc,3))

get_clf_eval(y_test, preds, pred_probs)

예측결과를 실제값과 비교해 평가하기 위해 get_clf_eval() 함수를 작성했다.

결과값에 대한 설명은 딱히 필요 없을 듯 하다.

 

 

 

Feature Importance 시각화

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10,12))
plot_importance(xgb_model, ax=ax)

첫 실습코드에 추가했던 xgboost의 plot_importance()를 실행한 결과.

여러 피쳐 중에 피쳐중요도가 높은 순으로 plot해주는 편리한 함수다.

 

 

 

Conclusion

XGBoost를 이해하기 위해 코드공부를 했다.

다음번에는 사이킷런의 xgboost를 공부해볼 예정이다.

 

Reference

파이썬 머신러닝 완벽 가이드 - 권철민

 

 

댓글