본문 바로가기

Machine Learning Models/Classic

Feature Selection - Permutation Feature Importance

반응형

이번 포스트에서 다룰 permutation feature importance는 모델을 재학습시킬 필요 없이 학습시킨 후에 feature 의 값을 랜덤하게 섞은 이후의 (permute) 성능 감소를 통해 feature importance를 측정하는 방법으로 매우 직관적입니다. 어떠한 feature를 랜덤하게 섞었을 때의 모델의 예측 에러가 증가했다면 중요한 feature로 판단할 수 있고 모델의 예측 에러가 거의 변동이 없다면 중요하지 않은 feature라 판단할 수 있습니다. 

훈련된 모델 $f$와 feature matrix $X$, 타겟 변수 $y$, 원래의 에러 $e_{org}=L(y,f(X))$가 있을때, 각 feature $j$에 대한 $X$에서 $j$번째 열을 임의로 섞어 만든 permuted feature matrix $X_{perm}$에 대한 에러 $e_{perm}=L(y,f(X_{perm}))$을 구한 이후 $e_{org}$에 대한 비율을 통해 각 feature에 대한 importance를 계산합니다.

데이터가 $n$개 존재할때 permutation 경우의 수는 $n(n-1)$이 되므로 데이터가 매우 많을 경우 전체 데이터셋을 절반으로 나누어 나눠진 절반끼리 swap하는 것으로 permutation을 대체하기도 합니다. 또한, 에러의 비율이나 차이를 통해 importance를 측정하는데 차이보다는 비율을 쓰는 것이 다른 문제와도 비교가 가능하기 때문에 일반적으로 에러의 비율을 importance 측정 방법으로 사용합니다.

특징

Permutation feature importance는 모델을 재학습시킬 필요 없이 에러의 상대적인 증가로 feature importance를 측정하기 때문에 시간/자원적으로 효율적이고 쉽게 구현이 가능합니다. 따라서 훈련 데이터셋이 아닌 validation/test 데이터셋에 대해 feature importance를 측정하는 것이 일반적입니다. 또한, 단순히 해당 feature를 섞어주기만 하면 되기 때문에 훈련된 모델과 데이터만 있으면 어떠한 모델에 대해서도 쉽게 적용이 가능합니다.

다른 중요한 특징으로는 feature를 랜덤하게 섞어 타겟 변수와의 관계를 끊음과 동시에 다른 feature들과의 상호작용 또한 끊어지게 된다는 점입니다. 따라서 두 feature의 상호작용의 영향 또한 feature importance 계산에 포함되므로 각 feature의 독립적인 partial importance라 볼 수 없습니다. 또한 랜덤하게 feature를 섞으므로 수행 시마다 결과가 매우 상이해집니다. 이는 permutation 횟수를 늘려 평균을 내는 방법으로 오차의 분산을 줄일 수 있으나 시간이 오래 걸리게 됩니다. 

특히 feature끼리 correlated 되어 있다면 비현실적인 데이터에 대해 feature importance가 편향될 수 있습니다. 예를 들어 키와 몸무게와 같이 어느 정도 연관이 있는 feature들이 존재할때 키가 2m이고 몸무게가 30kg인 비현실적인 데이터는 에러를 굉장히 증가시킬 것이므로 feature importance가 굉장히 부풀려질 가능성이 있습니다. 따라서 permutation feature importance 결과를 해석할 때 어떠한 feature끼리 correlated 되어 있는지 염두해 두어야 합니다.

이것의 연장선 상의 문제로 correlated 된 feature를 추가할 때 feature importance가 correlated feature에 분산될 가능성 또한 존재합니다. 타겟 변수에 지대한 영향을 끼치는 feature A가 있고 A와 크게 연관된 B feature를 추가시켰을 때 A 또는 B 한 개의 feature만 존재하더라도 충분히 예측을 잘 할수 있습니다. 즉, B가 없었을 때의 A의 feature importance가 매우 컸었다면 B의 추가로 인해 A의 feature importance가 부분적으로 B로 넘어가게 된다는 것입니다. 따라서 feature A가 원래라면 매우 중요했을 feature 였지만 B로 인해 덜 중요했던 다른 feature 들에 비해 importance 순위가 낮아져 해석에 부정적인 영향을 미칠 가능성이 존재합니다.

 

Example

실험 데이터로 Adult Census Income 데이터를 이용합니다. 이 데이터는 평균 연봉을 나타내는 income 칼럼을 예측하는 문제로 타겟 변수 income은 평균 연봉이 오만불 이상/이하인 범주형 데이터이고 성별, 결혼여부, 국적, 직업, 교육, 자본소득 등의 feature로 구성되어 있습니다. 

먼저 적절한 전처리를 수행한 후 XGBClassifier를 통해 간단히 훈련시킨 이후에,

import xgboost 
from xgboost import XGBClassifier
from sklearn import metrics

xgb = XGBClassifier(random_state=0, n_estimators=300).fit(X_train, y_train)

print('train accuracy: ',metrics.accuracy_score(y_train, xgb.predict(X_train)))
print('test accuracy: ', metrics.accuracy_score(y_test, xgb.predict(X_test)))

scikit-learn 패키지의 permutation_importance 함수를 통해 쉽게 permutation feature importance를 구할 수 있습니다.

from sklearn.inspection import permutation_importance

r = permutation_importance(xgb, X_test, y_test, n_repeats=30, random_state=0)

permutation_importance 함수에는 훈련시킨 모델의 객체, X/Y, permutation 반복 횟수 (n_repeats)를 넣어주어야 하며 결과는 딕셔너리 형태로 반복 횟수에 따른 에러 비율, 각 feature 별 importance의 평균, 표준 오차가 담겨 있습니다.

features = dict()

for i in r.importances_mean.argsort()[::-1]:
    if r.importances_mean[i] - 2 * r.importances_std[i] > 0:
        features[X.columns[i]] = r.importances[i]
        print(f"{X.columns[i]:<8}\t"
              f"{r.importances_mean[i]:.3f}"    
              f" +/- {r.importances_std[i]:.3f}")

seaborn 패키지의 boxplot 등의 함수를 통해 시각화해서 살펴볼 수 있습니다.

feature_df = pd.DataFrame(features)

ax = sns.boxplot(data=feature_df)
ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
plt.show()

 

참조

반응형