본문 바로가기

Machine Learning Models/Classic

Feature Selection - XGBoost

반응형

XGBOOST 동작 원리

Feature Selection - Random Forest (1)

Feature Selection - Random Forest (2)

LightGBM feature importance


지난 포스트에서도 살펴봤듯이 의사결정나무 기반의 앙상블 모델은 feature importance 함수를 지원합니다. scikit-learn 패키지의 의사결정나무/Random Forest 의 feature importance 는 Gini impurity (MDI) 기반의 feature importance 만을 지원하는 반면 XGBoost/LightGBM과 같은 부스팅 기반의 모델들은 다양한 방법의 importance 측정을 지원합니다. 이번 포스트에서는 XGBoost의 feature importance 구하는 법을 알아보도록 하겠습니다

Importance types

XGBoost에서 지원하는 importance 타입은 1) weight, 2) gain / total gain, 3) cover / total cover 가 있습니다.

Gain / Total gain

기본으로 지정되어 있는 타입입니다. 이름에서 유추할 수 있듯이 해당 feature가 모델 예측에 어느정도 영향을 미쳤는가를 측정하는 방법으로 노드가 특정 feature로 분기되었을 때 얻는 성능 상의 이득입니다. 지난 포스트에서 다루었던 Gini impurity 와 비슷합니다. Gain 타입은 feature가 사용된 전체 노드의 평균 gain 이며 total gain 타입은 feature가 사용된 전체 노드의 gain의 총합입니다.

Cover / Total cover

Cover 타입은 해당 feature와 관련된 샘플의 상대적인 개수입니다. 예를 들어 4개의 feature를 가진 100개의 샘플을 3개의 의사결정나무로 훈련시키고 feature 1이 10/5/2 개의 샘플을 각각 tree1/tree2/tree3 에서 구분했다고 가정했을 때 feature 1의 절대적인 cover 타입 개수는 17이 됩니다. Cover 타입은 해당 feature가 관여한 샘플의 평균 수이고 total cover 타입은 총합입니다.

Weight

Weight 타입은 해당 feature가 노드 분기에 사용된 횟수입니다. 예를 들어 feature 1이 분기 2/1/3 회만큼 tree1/tree2/tree3 에 사용되었을 때 weight 타입의 feature1 importance는 6이 되게 됩니다.

Examples

각 중요도 타입별 양상은 어떨까요? 예를 들어 성별이라는, 2개의 범주로 나누어지면서 타겟 변수에 크게 영향을 끼치는 변수가 있다고 합시다. 나이 혹은 다양한 값을 가질 수 있는 변수는 각 의사결정나무 내에서 여러 번 사용될 수 있는 반면 성별은 2개의 범주 밖에 없으므로 각 의사결정나무에서 최대 단 한 번만 사용될 것입니다. 따라서 weight 타입으로 feature importance를 측정할 경우 성별 변수는 중요도가 매우 낮게 측정될 것이며 cover/gain 타입에 대해서는 높게 측정될 것입니다.

XGBoost 패키지는 "feature_importances_" 라는 속성으로 기본 feature importance를 제공합니다. 단, XGBClassifier/XBGRegressor 객체를 선언할 때 importance_type 파라미터가 설정된 타입으로 출력되며 디폴트는 "gain" 타입으로 설정되어 있습니다. 또한 각 feature importance 의 합이 1이 되도록 상대적인 비율을 출력합니다.

주의할 점은 XGBoost의 부스팅기법의 앙상블을 이루는 약한 모델은 의사결정나무를 이용한 'gbtree', 선형모델인 'gblinear', 의사결정나무에 dropout을 적용한 'dart' 로 구성되어 있는데, "feature_importance_" 속성은 booster 파라미터가 'gbtree' 일때만 지원한다는 점입니다. 'gblinear' 의 경우 선형 모델이므로 feature importance를 계산하는 일반적인 방법이 애매하기 때문이고 'dart' 같은 경우 버젼에 따라 지원 여부가 다릅니다.

from xgboost import XGBClassifier

xgb = XGBClassifier(booster='gbtree', importance_type='gain')
xgb.fit(X, y)
xgb.feature_importances_

또한, xgboost 의 plot_importance 함수로 importance_type에 따른 feature importance를 볼 수 있습니다.

import xgboost
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(20,8))

axes = [ax for row_axes in axes for ax in row_axes]

xgboost.plot_importance(xgb, importance_type='gain', title='gain', xlabel='', grid=False, ax=axes[0])
xgboost.plot_importance(xgb, importance_type='cover', title='cover', xlabel='', grid=False, ax=axes[1])
xgboost.plot_importance(xgb, importance_type='weight', title='weight', xlabel='', grid=False, ax=axes[2])
xgboost.plot_importance(xgb, importance_type='total_gain', title='total_gain', xlabel='', grid=False, ax=axes[3])
xgboost.plot_importance(xgb, importance_type='total_cover', title='total_cover', xlabel='', grid=False, ax=axes[4])
plt.tight_layout()
plt.show()

 

참조

 

반응형