2023.09.04 - [AI,머신러닝] - XGBoost 피쳐 중요도
https://mljar.com/blog/feature-importance-in-random-forest/
https://christophm.github.io/interpretable-ml-book/feature-importance.html
https://velog.io/@73syjs/%ED%8A%B9%EC%84%B1-%EC%A4%91%EC%9A%94%EB%8F%84Feature-Importances
트리 모델의 피쳐 중요도를 측정하는 방법에는 다음과 같은 것들이 있다.
- Mean Decrease in Impurity (MDI) (= Gini Importance)
- Permutation Importance ($\approx$ Mean Decrease in Accuracy, MDA)
- Drop-Column Importance
Scikit learn Random forest 모델에는 MDI 방식의 피쳐 중요도가 기본 제공되며, Permutation importance 방식은 Random forest와 Gradient boosting 모델(XGBoost, LightGBM, ...) 모두 사용 가능하다.
XGBoost, LightGBM에도 MDI와 유사하게 Split-based 및 Gain-based 피쳐 중요도가 기본 제공된다.
모델에 상관없이 SHAP을 사용할 수도 있다.
Mean Decrease in Impurity (MDI)
Gini Importance라고도 불림
총 노드 불순도 감소량을 샘플 비율 가중치 적용하여 합산 후 평균 계산 (RF 모든 트리에 걸쳐)
In scikit-learn, we implement the importance as described in [1] (often cited, but unfortunately rarely read...). It is sometimes called "gini importance" or "mean decrease impurity" and is defined as the total decrease in node impurity (weighted by the probability of reaching that node (which is approximated by the proportion of samples reaching that node)) averaged over all trees of the ensemble.
[1]: Breiman, Friedman, "Classification and regression trees", 1984.
예를 들어, 피쳐 A를 기준으로 데이터셋 $D$를 $D_1, D_2$로 나누고, 각각의 크기가 $n_1, n_2$일 때, 해당 노드에서의 피쳐 A의 불순도 감소량은 다음과 같다.
$ Gini_A(D) = \cfrac{n_1}{n}Gini(D_1) + \cfrac{n_2}{n}Gini(D_2) $
Scikit learn의 RandomForestClassifier, RandomForestRegressor에 기본 내장되어 있으며, feature_importances_
로 참조할 수 있다.
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.ensemble import RandomForestRegressor
dataset = load_diabetes()
X = pd.DataFrame(dataset.data, columns=dataset.feature_names)
y = dataset.target
rf = RandomForestRegressor(n_estimators=100)
rf.fit(X, y)
rf.feature_importances_
array([0.06581037, 0.01214194, 0.24914275, 0.09259311, 0.04701703,
0.05583914, 0.05292121, 0.02061662, 0.33420787, 0.06970997])
import matplotlib.pyplot as plt
plt.barh(dataset.feature_names, rf.feature_importances_)
- 단점
- 수치형 변수, cardinality 높은 변수의 중요도가 높게 나오는 경향이 있음
- 훈련 데이터셋만 반영하므로 테스트 셋을 통한 검증 불가
Permutation Importance
Mean Decrease in Accuracy(MDA)라고도 불림 (중요도 측정 지표로 accuracy 사용 시)
Out-of-bag(OOB) 샘플, 또는, 훈련 데이터와 구분되는 테스트 데이터 사용
샘플 데이터의 정확도(accuracy)와 특정 피쳐 데이터를 랜덤하게 재배열했을 때의 정확도 감소량을 통해 피쳐 중요도 측정
Scikit learn에 permutation_importance
함수로 구현되어 있다.
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import permutation_importance
import matplotlib.pyplot as plt
dataset = load_diabetes()
X = pd.DataFrame(dataset.data, columns=dataset.feature_names)
y = dataset.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=12)
rf = RandomForestRegressor(n_estimators=100)
rf.fit(X_train, y_train)
importances = permutation_importance(rf, X_test, y_test)
plt.barh(dataset.feature_names, importances.importances_mean)
- 단점
- 일부 피쳐들 사이에 상관관계가 높은 경우 데이터 재배열이 데이터를 비현실적으로 만듦으로써 피쳐 중요도가 편향될 수 있음
(If features are correlated, the permutation feature importance can be biased by unrealistic data instances.)
예를 들어, "키", "몸무게" 피쳐가 포함된 데이터를 재배열하면, 2미터에 30Kg처럼 비현실적인 데이터가 만들어지면서 중요도 측정이 올바르지 않을 수 있음
(상관관계가 높은 피쳐들의 중요도가 높게 측정될 수 있음 https://blog.ceshine.net/post/please-stop-permuting-features/) - 피쳐 상관관계가 매우 강할 경우 두 피쳐가 중요도를 나눠가지는 문제도 있음
예를 들어, 성별 구분을 위해 "남자", "여자" 피쳐를 모두 사용하면, random forest에서 어떤 트리는 "남자" 피쳐만을, 어떤 트리는 "여자" 피쳐만을 사용하게 되어 피쳐 중요도가 양분될 수 있음
- 일부 피쳐들 사이에 상관관계가 높은 경우 데이터 재배열이 데이터를 비현실적으로 만듦으로써 피쳐 중요도가 편향될 수 있음
Drop-Column Importance
Permutation importance의 상관관계 이슈 해결을 위한 대안이 될 수 있음
피쳐를 하나씩 제거하면서 정확도 감소량을 통해 중요도 측정
각 피쳐 중요도를 구할 때마다 트리 재학습 필요
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
dataset = load_diabetes()
X = pd.DataFrame(dataset.data, columns=dataset.feature_names)
y = dataset.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=12)
rf = RandomForestRegressor(n_estimators=100)
rf.fit(X_train, y_train)
score = rf.score(X_test, y_test)
rf_bmi = RandomForestRegressor(n_estimators=100)
rf_bmi.fit(X_train.drop(columns='bmi'), y_train)
score_wo_bmi = rf_bmi.score(X_test.drop(columns='bmi'), y_test)
print(f"score: {score}")
print(f"score w/o bmi: {score_wo_bmi}")
print(f"bmi 중요도: {score - score_wo_bmi}")
score: 0.3141066381390939
score w/o bmi: 0.1619839553539244
bmi 중요도: 0.1521226827851695
Gradient Boosting 모델 Split-based 및 Gain-based 피쳐 중요도
(LightGBM) importance_type (string, optional (default=”split”)) — How the importance is calculated. If “split”, result contains numbers of times the feature is used in a model. If “gain”, result contains total gains of splits which use the feature.
(XGBoost) ‘weight’ — the number of times a feature is used to split the data across all trees. ‘gain’ — the average gain of the feature when it is used in trees ‘cover’ — the average coverage of the feature when it is used in trees, where coverage is defined as the number of samples affected by the split
LightGBM split, XGBoost weight는 피쳐가 split에 사용된 횟수를 기준으로 피쳐 중요도를 측정한다.
gain은 (MDI에서의 Gini impurity처럼) 해당 피쳐로 분할했을 때 줄어든 손실의 합으로 계산한다.
XGBoost cover는 각 피쳐에 영향을 받은 샘플 수로 계산한다.
XGBoost.Booster.get_score
https://xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.Booster.get_score
get_score(fmap='', importance_type='weight')
Get feature importance of each feature. For tree model Importance type can be defined as:
- ‘weight’: the number of times a feature is used to split the data across all trees.
- ‘gain’: the average gain across all splits the feature is used in.
- ‘cover’: the average coverage across all splits the feature is used in.
- ‘total_gain’: the total gain across all splits the feature is used in.
- ‘total_cover’: the total coverage across all splits the feature is used in.
SHAP
2023.09.04 - [AI,머신러닝] - SHAP (ML 모델 피쳐 중요도 측정)
'AI,머신러닝' 카테고리의 다른 글
Gradient Boosting (XGBoost, LightGBM, CatBoost 비교) (0) | 2023.09.19 |
---|---|
SHAP (ML 모델 피쳐 중요도 측정) (0) | 2023.09.04 |
의사결정 트리(Decision Tree) - CART 알고리즘 (0) | 2023.08.24 |
의사결정 트리(Decision Tree) - C4.5 알고리즘 (0) | 2023.08.24 |
의사결정 트리 (Decision Tree) (0) | 2023.08.24 |