Feature Importances


Applied Predictive Modeling


1. Permutation Importances

Q . Permutation Importances( 순열중요도 )란?
A . 검증데이터에서 각 특성을 제거하지 않고 특성값에 무작위로 노이즈를 주어 기존 정보를 제거하여 특성이 기존에 하던 역할을 하지 못하게 하고 성능을 측정한다.

  • 이때 노이즈를 주는 가장 간단한 방법이 그 특성값들을 샘플들 내에서 섞는 것( shuffle, permutation )이다.
  • 순열 중요도는 기본 특성 중요도와 Drop-column 중요도 중간에 위치하는 특징을 가진다고 볼 수 있다.
  • 중요도 측정은 관심있는 특성에만 무작위로 노이즈를 주고 예측을 하였을 때 성능 평가지표( 정확도, F1, R2R^2 등 )가 얼마나 감소하는지를 측정한다.
  • Drop-column 중요도를 계산하기 위해 재학습을 해야한다.
  • 칼럼 노이즈 -> (1번만)fit -> score
import eli5
from eli5.sklearn import PermutationImportance

# permuter 정의
permuter = PermutationImportance(
    pipe.named_steps['rf'], # model
    scoring='accuracy', # metric
    n_iter=5, # 다른 random seed를 사용하여 5번 반복
    random_state=2
)

# permuter 계산은 preprocessing 된 X_val을 사용합니다.
X_val_transformed = pipe.named_steps['preprocessing'].transform(X_val)

# 실제로 fit 의미보다는 스코어를 다시 계산하는 작업입니다
permuter.fit(X_val_transformed, y_val);

feature_names = X_val.columns.tolist()
pd.Series(permuter.feature_importances_, feature_names).sort_values()

# 특성별 score 확인
eli5.show_weights(
    permuter, 
    top=None, # top n 지정 가능, None 일 경우 모든 특성 
    feature_names=feature_names # list 형식으로 넣어야 합니다
)

1.1 Feature Importance( Mean Decrease Impurity, MDI )

Q . Feature Importance란?
A . 각각 특성을 모든 트리에 대해 평균불순도감소(mean decrease impurity)를 계산한 값이다.

  • sklearn 트리 기반 분류기에서 디폴트로 사용되는 특성 중요도는 속도는 빠르지만 결과를 주의해서 봐야 한다.
  • High cardinalty 특성이 특성 중요도가 높게 나올 수 있다.
    • Class가 많으면 feature가 중요하지 않아도 불순도가 낮아지기 때문에 특성 중요도가 높게 나온다.

불순도 감소(impurity decrease)는 다음과 같이 계산한다.

NtN(ImNtRNtRImNtLNtLIm)\displaystyle \frac{N_t}{N}*(Im-\displaystyle\frac{N_{tR}}{N_t}* RIm-\displaystyle\frac{N_{tL}}{N_t} * LIm)

  • ImIm : Impurity
  • RImRIm : Right_Impurity
  • LImLIm : Left_Impurity
  • NN: 전체 관측치 수
  • NtN_t: 현재 노드 t에 존재하는 관측치 수
  • NtLN_{tL}: 노드 t 왼쪽( L ) 자식노드에 존재하는 관측치 수
  • NtRN_{tR}: 노드 t 오른쪽( R ) 자식노드에 존재하는 관측치 수
  • 만약 sample_weight가 주어진다면, NN, NtN_t, NtRN_{tR}, NtLN_{tL}는 가중합을 합니다.
# 특성 중요도
rf = pipe.named_steps['randomforestclassifier']
importances = pd.Series(rf.feature_importances_, X_train.columns)

%matplotlib inline
import matplotlib.pyplot as plt

n = 20
plt.figure(figsize=(10,n/2))
plt.title(f'Top {n} features')
importances.sort_values()[-n:].plot.barh();

1.2 Drop-Column Importance

Q . Drop-Column Importance란?
A . 매 특성을 drop한 후 fit을 다시한다.

  • 단점 : 매우 느리다
  • 칼럼 하나씩 제거 -> fit -> score
  • 특성이 n개 존재할 때 n+1번 학습이 필요하다.
column  = 'opinion_seas_risk'

# opinion_h1n1_risk 없이 fit
pipe = make_pipeline(
    OrdinalEncoder(), 
    SimpleImputer(), 
    RandomForestClassifier(n_estimators=100, random_state=2, n_jobs=-1)
)
pipe.fit(X_train.drop(columns=column), y_train)
score_without = pipe.score(X_val.drop(columns=column), y_val)
print(f'검증 정확도 ({column} 제외): {score_without}')

# opinion_h1n1_risk 포함 후 다시 학습
pipe = make_pipeline(
    OrdinalEncoder(), 
    SimpleImputer(), 
    RandomForestClassifier(n_estimators=100, random_state=2, n_jobs=-1)
)
pipe.fit(X_train, y_train)
score_with = pipe.score(X_val, y_val)
print(f'검증 정확도 ({column} 포함): {score_with}')

# opinion_h1n1_risk 포함 전 후 정확도 차이를 계산한다.
print(f'{column}의 Drop-Column 중요도: {score_with - score_without}')

2. Boosting

Q . 부스팅과 배깅의 차이점은?
A . 트리를 만드는 방법에 차이가 있다. 배깅의 경우 각 트리를 독립적으로 만들지만 부스팅은 만들어지는 트리가 이전에 만들어진 트리에 영향을 받는다.

분류문제를 풀기 위해서는 트리 앙상블 모델을 많이 사용합니다.

  • 트리 앙상블은 랜덤포레스트나 그래디언트 부스팅 모델을 이야기 하며 여러 문제에서 좋은 성능을 보이는 것을 확인하였다.
  • 트리모델은 non-linear, non-monotonic 관계, 특성간 상호작용이 존재하는 데이터 학습에 적용하기 좋다.
  • 한 트리를 깊게 학습시키면 과적합을 일으키기 쉽기 때문에, 배깅( Bagging, 랜덤포레스트 )이나 부스팅(Boosting) 앙상블 모델을 사용해 과적합을 피한다.
  • 랜덤포레스트의 장점은 하이퍼파라미터에 상대적으로 덜 민감한 것인데, 그래디언트 부스팅의 경우 하이퍼파라미터 셋팅에 따라 랜덤포레스트 보다 더 좋은 예측 성능을 보여줄 수도 있다.

2.1 AdaBoost

Q . AdaBoost란?
A . 각 트리( 약한 학습기들, weak learners )가 만들어질 때 잘못 분류되는 관측치에 가중치를 준다. 그리고 다음 트리가 만들어질 때 이전에 잘못 분류된 관측치가 더 많이 샘플링되게 하여 그 관측치를 분류하는데 더 초점을 맞춘다.

  • AdaBoost의 알고리즘 예시
    • Step 0. 모든 관측치에 대해 가중치를 동일하게 설정한다.
    • Step 1. 관측치를 복원추출 하여 약한 학습기 Dn을 학습하고 +, - 분류한다.
    • Step 2. 잘못 분류된 관측치에 가중치를 부여해 다음 과정에서 샘플링이 잘되도록 한다.
    • Step 3. Step 1~2 과정을 n회 반복( n = 3 )한다.
    • Step 4. 분류기들(D1, D2, D3)을 결합하여 최종 예측을 수행한다.

  • AdaBoost 알고리즘

최종 학습기 H(x)약한 학습기들(hth_t)의 가중(α\alpha)합으로 만들어진다.
여기서 αt\alpha_t 가 크면 ete_t가 작다는 것으로 분류기 hth_t 성능이 좋다는 것이고
여기서 αt\alpha_t 가 작으면 ete_t가 크다는 것으로 분류기 hth_t 성능이 안좋다는 뜻이다.

2.2 Gradient Boosting

Q . Gradient Boosting이란?
A . 그래디언트 부스팅은 샘플의 가중치를 조정하는 대신 잔차(residual)을 학습하도록 한다. 이것은 잔차가 더 큰 데이터를 더 학습하도록 만드는 효과가 있다.

  • 그래디언트 부스팅은 AdaBoost와 유사하지만 비용함수( Loss function )을 최적화하는 방법에 있어서 차이가 있다.
  • Gradient Boosting은 회귀문제, 분류문제에 모두 사용할 수 있다.

2.3 xgboost

  • xgboost 는 랜덤포레스트보다 하이퍼파라미터 셋팅에 민감합니다
from xgboost import XGBClassifier

pipe = make_pipeline(
    OrdinalEncoder(),
    SimpleImputer(strategy='median'),
    XGBClassifier(n_estimators=200
                  , random_state=2
                  , n_jobs=-1
                  , max_depth=7
                  , learning_rate=0.2
                 )
)

pipe.fit(X_train, y_train);

from sklearn.metrics import accuracy_score
y_pred = pipe.predict(X_val)
print('검증 정확도: ', accuracy_score(y_val, y_pred))

print(classification_report(y_pred, y_val))

Early Stopping을 사용하여 과적합을 피한다.
Q .왜 n_estimators 최적화를 위해 GridSearchCV나 반복문 대신 early stopping을 사용할까?
A . n_iterations 가 반복수라 할때, early stopping을 사용하면 우리는 n_iterations 만큼의 트리를 학습하면 된다.
하지만 GridSearchCV나 반복문을 사용하면 무려 sum(range(1,n_rounds+1)) 트리를 학습해야 한다!
거기에 max_depth, learning_rate 등등 파라미터 값에 따라 더 돌려야 한다.
따라서, early stopping을 잘 활용하는게 훨씬 효과적이다.

타겟 비율이 균형이 안맞을 때는 클래스에 weight를 주기 위해 ratio를 계산한다


3. 하이퍼파라미터 튜닝

Random Forest

  • max_depth (높은값에서 감소시키며 튜닝, 너무 깊어지면 과적합)
  • n_estimators (적을경우 과소적합, 높을경우 긴 학습시간)
  • min_samples_leaf (과적합일경우 높임)
  • max_features (줄일 수록 다양한 트리생성, 높이면 같은 특성을 사용하는 트리가 많아져 다양성이 감소)
  • class_weight (imbalanced 클래스인 경우 시도)

XGBoost

  • learning_rate (높을경우 과적합 위험이 있습니다)
  • max_depth (낮은값에서 증가시키며 튜닝, 너무 깊어지면 과적합위험, -1 설정시 제한 없이 분기, 특성이 많을 수록 깊게 설정)
  • n_estimators (너무 크게 주면 긴 학습시간, early_stopping_rounds와 같이 사용)
  • scale_pos_weight (imbalanced 문제인 경우 적용시도)


👉 과정 한눈에 보기

profile
기록하지 않으면 기록되지 않는다.

0개의 댓글