Machine Learning/캐글스터디(파이썬 머신러닝)

[4-3장] XGBoost과 LightGBM

뉴욕킴 2023. 5. 22. 22:21

XGBoost

  • 트리 기반의 앙상블 학습 중 가장 각광받는 알고리즘(분류에 있어 뛰어난 예측 성능 지님)
  • 특징: 뛰어난 예측 성능, 빠른 수행 시간, 과적합 규제 기능, tree pruning 기능, 자체 내장된 교차 검증 수행 능력, 결손값 자체 처리 기능 

 

XGBoost를 이용한 위스콘신 유방암 예측

  • 위스콘신 유방암 데이터: 종양의 크기, 모양 등의 다양한 속성값을 기반으로 악성/ 양성 종양 분류하는 데이터 세트 
  • 데이터 세트 로딩 하기
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# xgboost 패키지 로딩하기
import xgboost as xgb
from xgboost import plot_importance

import warnings
warnings.filterwarnings('ignore')

dataset = load_breast_cancer()
features= dataset.data
labels = dataset.target

cancer_df = pd.DataFrame(data=features, columns=dataset.feature_names)
cancer_df['target']= labels
cancer_df.head(3)
  • 수많은 속성이 숫자로 되어 있는 것 확인 

# 레이블 값의 분포 확인 

print(dataset.target_names)
print(cancer_df['target'].value_counts())

  • 양성 357개, 악성 212개 구성된 것 확인

# 데이터 세트를 80% 학습용, 20% 테스트용으로 추출한 뒤
→ 80% 학습용 데이터에서 90%를 최종 학습용, 10%를 검증용으로 분할 진행 

# cancer_df에서 feature용 DataFrame과 Label용 Series 객체 추출
# 맨 마지막 칼럼이 Label이므로 Feature용 DataFrame은 cancer_df의 첫번째 칼럼에서 맨 마지막 두번째 컬럼까지를 :-1 슬라이싱으로 추출.
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 )

print(X_train.shape , X_test.shape)
print(X_tr.shape, X_val.shape)
더보기
(455, 30) (114, 30)
(409, 30) (46, 30)
  • 최종 학습용 409개, 검증용 46개, 테스트용 114개 추출 확인

 
학습과 예측 데이터 세트를 DMatrix로 변환

  • DMatrix는 넘파이 array, DataFrame에서도 변환 가능
# 만약 구버전 XGBoost에서 DataFrame으로 DMatrix 생성이 안될 경우 X_train.values로 넘파이 변환. 
# 학습, 검증, 테스트용 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)
  • 하이퍼 파라미터 설정
params = { 'max_depth':3,
           'eta': 0.05,
           'objective':'binary:logistic',
           'eval_metric':'logloss'
        }
num_rounds = 400
  • 주어진 하이퍼 파라미터와 early stopping 파라미터를 train( ) 함수의 파라미터로 전달하고 학습
  • max_depth: 트리 최대 깊이
  • eta: 학습률
  • logistic: 예제 데이터가 0 또는 1 이진 분류
  • eval_metric: logloss -> 오류 함수의 평가 성능 지표는 logloss
  • num_rounds: 부스팅 반복 횟수

# 학습 데이터 셋은 'train' 또는 평가 데이터 셋은 'eval' 로 명기합니다. 
eval_list = [(dtr,'train'),(dval,'eval')] # 또는 eval_list = [(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 )
  • 반복시마다 train-logloss와 eval-logloss 감소 확인
  • num_boost_round를 500회로 설정해도 176번에서 끝나는거 확인
  • logloss 값이 작을수록 성능이 가장 좋음 -> 가장 작은 값 확인


# predict()를 통해 예측 확률값을 반환하고 예측 값으로 변환

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

# 예측 확률이 0.5 보다 크면 1 , 그렇지 않으면 0 으로 예측값 결정하여 List 객체인 preds에 저장 
preds = [ 1 if x > 0.5 else 0 for x in pred_probs ]
print('예측값 10개만 표시:',preds[:10])
더보기
predict( ) 수행 결과값을 10개만 표시, 예측 확률 값으로 표시됨
[0.845 0.008 0.68  0.081 0.975 0.999 0.998 0.998 0.996 0.001]
예측값 10개만 표시: [1, 0, 1, 0, 1, 1, 1, 1, 1, 0]
pred_probs
  • get_clf_eval( )을 통해 예측 평가
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import 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 = roc_auc_score(y_test, pred_proba)
    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))
get_clf_eval(y_test , preds, pred_probs)
더보기
오차 행렬
[[34  3]
 [ 2 75]]
정확도: 0.9561, 정밀도: 0.9615, 재현율: 0.9740,    F1: 0.9677, AUC:0.9937

 

LightGBM

- 더 빠른 학습과 예측 수행 시간
- 더 작은 메모리 사용량  
- 카테고리형 피처의 자동 변환, 최적분할 (원-핫 인코딩 사용하지 않고 카테고리형 피처를 최적으로 변환하고 이에 따른 노드 분할 수행)
→ 굉장히 많이 사용함 / 리프 중심으로 트리를 분할함! 
- 단점: 적은 데이터 세트(10,000건 이하 데이터 세트)에 적용할 경우 과적합 발생 쉬움

  • 트리 균형을 맞추지 않고 최대 손실값을 가지는 리프 노드를 지속적으로 분할하면서 트리 깊이 깊어지고 비대칭적 규칙 트리 생성됨 → 예측 오류 손실 최소화 장점

주요 파라미터

  • num_iterations[default = 100]: 반복 수행하려는 트리 개수 지정
  • learning_rate[default = 0.1]: 0에서 1 사이의 값 지정하며 부스팅 스텝 반복적으로 수행 시 업데이트 되는 학습률 값
  • min_data_in_leaf: 최종 결정 클래스인 리프 노드가 되기 위해 필요한 최소한의 레코드 수/ 과적합 제어 위한 파라미터
  • num_leaves[default = 31]: 하나의 트리가 가질 수 있는 최대 리프 개수
  • boosting[default = gbdt]: 부스팅 트리 생성하는 알고리즘 기술
  • bagging_fraction[default = 1.0]: 커진 트리 과적합 제어 위해 데이터 샘플링 비율 지정
  • feature_fraction[default = 1.0]: 개별 트리 학습할 때마다 무작위로 선택하는 피처의 비율/ 과적합 제어 위함
  • lambda_l2[default = 0.0]: L2 regulation 제어를 위한 값. 피처 개수 많을 경우 적용을 검토하며 값이 클수록 과적합 감소 효과 있음
  • lambda_l2[default = 0.0]: L1 regulation 제어를 위한 값/ 과적합 제어를 위함  

 

하이퍼 파라미터 튜닝 방안 (과적합 개선) 

  • num_leaves: 개별 트리가 가질 수 있는 최대 리프 개수, LightGBM 모델 복잡도 제어하는 주요 파라미터
  • min_data_in_leaf: 과적합 개선 위한 중요한 파라미터
  • max_depth: 깊이 크기 제한

 

LightGBM 적용 - 위스콘신 유방암 예측 

import lightgbm

print(lightgbm.__version__)
더보기
3.3.5
# LightGBM의 파이썬 패키지인 lightgbm에서 LGBMClassifier 임포트
from lightgbm import LGBMClassifier

import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
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 )

# 위에서 만든 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 )

# 앞서 XGBoost와 동일하게 n_estimators는 400 설정. 
lgbm_wrapper = LGBMClassifier(n_estimators=400, learning_rate=0.05)

# LightGBM도 XGBoost와 동일하게 조기 중단 수행 가능. 
evals = [(X_tr, y_tr), (X_val, y_val)]
lgbm_wrapper.fit(X_tr, y_tr, early_stopping_rounds=50, eval_metric="logloss", 
                 eval_set=evals, verbose=True)
preds = lgbm_wrapper.predict(X_test)
pred_proba = lgbm_wrapper.predict_proba(X_test)[:, 1]
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import 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 = roc_auc_score(y_test, pred_proba)
    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))
get_clf_eval(y_test, preds, pred_proba)
더보기
오차 행렬
[[34  3]
 [ 2 75]]
정확도: 0.9561, 정밀도: 0.9615, 재현율: 0.9740,    F1: 0.9677, AUC:0.9877
# plot_importance( )를 이용하여 feature 중요도 시각화
from lightgbm import plot_importance
import matplotlib.pyplot as plt
%matplotlib inline

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

* plot_importane 함수로 아래와 같이 시각화 가능 ↓

공식문서

Welcome to LightGBM’s documentation! — LightGBM 3.3.5 documentation

 

Welcome to LightGBM’s documentation! — LightGBM 3.3.5 documentation

© Copyright 2023, Microsoft Corporation. Revision ca035b2e.

lightgbm.readthedocs.io

논문 

[논문리뷰/설명] LightGBM: A Highly efficient Gradient Boosting Decision Tree (tistory.com)

 

[논문리뷰/설명] LightGBM: A Highly efficient Gradient Boosting Decision Tree

LightGBM은 예전에 한 프로젝트에서 정형 데이터 (Table 형태의 데이터) 에 여러 머신러닝 기법들을 적용해보던 중에 발견한 방법이었습니다. CPU만 사용하면서도 GPU를 쓰는 XGBoost보다 훨씬 더 빠르

kicarussays.tistory.com

참고 영상

04-8: Ensemble Learning - LightGBM (앙상블 기법 - LightGBM) - YouTube