031 특성 중요도 분석
키워드: 특성 중요도, feature importance, 해석
개요
특성 중요도(Feature Importance)는 모델이 예측을 할 때 각 특성이 얼마나 중요한 역할을 하는지 보여줍니다. 이를 통해 모델의 동작을 이해하고, 핵심 특성을 파악할 수 있습니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
flaml[automl], pandas, scikit-learn, matplotlib
pip install flaml[automl] pandas scikit-learn matplotlib
특성 중요도란?
개념
각 특성이 모델의 예측에 기여하는 정도를 수치화한 것입니다.
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from flaml import AutoML
# 031 데이터 준비
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 031 FLAML 학습
automl = AutoML()
automl.fit(
X_train, y_train,
task="classification",
time_budget=60,
metric="accuracy",
estimator_list=["lgbm", "xgboost", "rf"], # 트리 기반 모델
verbose=0
)
print(f"최적 모델: {automl.best_estimator}")
트리 기반 모델의 특성 중요도
feature_importances_ 속성
import matplotlib.pyplot as plt
# 031 특성 중요도 추출
if hasattr(automl.best_model, 'feature_importances_'):
importance = automl.best_model.feature_importances_
feature_names = X.columns
# DataFrame으로 정리
importance_df = pd.DataFrame({
'feature': feature_names,
'importance': importance
}).sort_values('importance', ascending=False)
print("특성 중요도 (상위 10개):")
print(importance_df.head(10).to_string(index=False))
# 시각화
plt.figure(figsize=(12, 8))
top_n = 15
top_features = importance_df.head(top_n)
plt.barh(range(top_n), top_features['importance'].values[::-1])
plt.yticks(range(top_n), top_features['feature'].values[::-1])
plt.xlabel('Importance')
plt.title('Feature Importance (Top 15)')
plt.tight_layout()
plt.show()
중요도 유형
# 031 LightGBM의 다양한 중요도 유형
if automl.best_estimator == 'lgbm':
model = automl.best_model
# 1. Split importance (분할 횟수 기반)
importance_split = model.feature_importances_
# 2. Gain importance (정보 이득 기반)
importance_gain = model.booster_.feature_importance(importance_type='gain')
# 비교
comparison = pd.DataFrame({
'feature': feature_names,
'split': importance_split,
'gain': importance_gain
}).sort_values('gain', ascending=False)
print("Split vs Gain 중요도 (상위 5개):")
print(comparison.head().to_string(index=False))
순열 중요도 (Permutation Importance)
개념
특성의 값을 무작위로 섞었을 때 성능이 얼마나 떨어지는지로 중요도를 측정합니다.
from sklearn.inspection import permutation_importance
# 031 순열 중요도 계산
perm_importance = permutation_importance(
automl.best_model, X_test, y_test,
n_repeats=10,
random_state=42,
n_jobs=-1
)
# 031 결과 정리
perm_df = pd.DataFrame({
'feature': feature_names,
'importance_mean': perm_importance.importances_mean,
'importance_std': perm_importance.importances_std
}).sort_values('importance_mean', ascending=False)
print("순열 중요도 (상위 10개):")
print(perm_df.head(10).to_string(index=False))
# 031 시각화
plt.figure(figsize=(12, 8))
top_n = 15
top_perm = perm_df.head(top_n)
plt.barh(range(top_n), top_perm['importance_mean'].values[::-1],
xerr=top_perm['importance_std'].values[::-1], capsize=3)
plt.yticks(range(top_n), top_perm['feature'].values[::-1])
plt.xlabel('Mean Importance (with std)')
plt.title('Permutation Feature Importance')
plt.tight_layout()
plt.show()
특성 중요도 vs 순열 중요도
| 항목 | 특성 중요도 | 순열 중요도 |
|---|---|---|
| 계산 방식 | 학습 중 계산 | 학습 후 계산 |
| 데이터 | 학습 데이터 | 검증/테스트 데이터 |
| 편향 | 고 카디널리티 특성에 편향 | 상대적으로 공정 |
| 속도 | 빠름 | 느림 |
| 상관 특성 | 과대평가 가능 | 과소평가 가능 |
중요도 분석 함수화
def analyze_feature_importance(model, X_train, X_test, y_test, feature_names=None):
"""종합적인 특성 중요도 분석"""
if feature_names is None:
feature_names = [f'feature_{i}' for i in range(X_train.shape[1])]
results = {}
# 1. 기본 특성 중요도 (트리 기반)
if hasattr(model, 'feature_importances_'):
results['tree_importance'] = pd.DataFrame({
'feature': feature_names,
'importance': model.feature_importances_
}).sort_values('importance', ascending=False)
# 2. 순열 중요도
perm = permutation_importance(model, X_test, y_test, n_repeats=10, random_state=42)
results['permutation_importance'] = pd.DataFrame({
'feature': feature_names,
'importance': perm.importances_mean,
'std': perm.importances_std
}).sort_values('importance', ascending=False)
return results
# 031 사용 예
importance_results = analyze_feature_importance(
automl.best_model, X_train, X_test, y_test, feature_names=list(X.columns)
)
print("트리 기반 중요도 Top 5:")
print(importance_results['tree_importance'].head().to_string(index=False))
print("\n순열 중요도 Top 5:")
print(importance_results['permutation_importance'].head().to_string(index=False))
특성 선택에 활용
중요도 기반 특성 선택
def select_features_by_importance(importance_df, threshold=0.01, top_n=None):
"""중요도 기반 특성 선택"""
if top_n:
selected = importance_df.head(top_n)['feature'].tolist()
else:
selected = importance_df[importance_df['importance'] >= threshold]['feature'].tolist()
return selected
# 031 상위 10개 특성 선택
top_features = select_features_by_importance(
importance_results['tree_importance'], top_n=10
)
print(f"선택된 특성 ({len(top_features)}개):")
for f in top_features:
print(f" - {f}")
# 031 선택된 특성으로 재학습
X_train_selected = X_train[top_features]
X_test_selected = X_test[top_features]
automl_selected = AutoML()
automl_selected.fit(
X_train_selected, y_train,
task="classification",
time_budget=30,
verbose=0
)
# 031 성능 비교
from sklearn.metrics import accuracy_score
y_pred_full = automl.predict(X_test)
y_pred_selected = automl_selected.predict(X_test_selected)
print(f"\n전체 특성 ({X_train.shape[1]}개) 정확도: {accuracy_score(y_test, y_pred_full):.4f}")
print(f"선택 특성 ({len(top_features)}개) 정확도: {accuracy_score(y_test, y_pred_selected):.4f}")
중요도 시각화 개선
그룹별 중요도
# 031 특성 그룹 정의 (유방암 데이터 예시)
feature_groups = {
'mean': [f for f in X.columns if 'mean' in f],
'se': [f for f in X.columns if 'error' in f],
'worst': [f for f in X.columns if 'worst' in f]
}
# 031 그룹별 중요도 합계
group_importance = {}
for group, features in feature_groups.items():
mask = importance_results['tree_importance']['feature'].isin(features)
group_importance[group] = importance_results['tree_importance'][mask]['importance'].sum()
print("그룹별 중요도:")
for group, imp in sorted(group_importance.items(), key=lambda x: -x[1]):
print(f" {group}: {imp:.4f}")
# 031 시각화
plt.figure(figsize=(8, 5))
plt.bar(group_importance.keys(), group_importance.values(), color=['blue', 'orange', 'green'])
plt.ylabel('Total Importance')
plt.title('Feature Group Importance')
plt.tight_layout()
plt.show()
히트맵 시각화
import seaborn as sns
# 031 상관관계와 중요도 결합
top_10_features = importance_results['tree_importance'].head(10)['feature'].tolist()
correlation = X[top_10_features].corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation, annot=True, cmap='coolwarm', center=0, fmt='.2f')
plt.title('Correlation Matrix of Top 10 Important Features')
plt.tight_layout()
plt.show()
중요도 안정성 분석
from sklearn.model_selection import cross_val_score
def importance_stability(model_class, X, y, n_runs=5):
"""여러 번 학습하여 중요도 안정성 확인"""
all_importances = []
for seed in range(n_runs):
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=seed
)
automl = AutoML()
automl.fit(
X_train, y_train,
task="classification",
time_budget=30,
seed=seed,
verbose=0
)
if hasattr(automl.best_model, 'feature_importances_'):
all_importances.append(automl.best_model.feature_importances_)
# 평균 및 표준편차
mean_importance = np.mean(all_importances, axis=0)
std_importance = np.std(all_importances, axis=0)
return pd.DataFrame({
'feature': X.columns,
'mean_importance': mean_importance,
'std_importance': std_importance,
'cv': std_importance / (mean_importance + 1e-10) # 변동계수
}).sort_values('mean_importance', ascending=False)
# 031 실행 (시간이 걸림)
# 031 stability_df = importance_stability(AutoML, X, y, n_runs=5)
# 031 print("중요도 안정성 (상위 10개):")
# 031 print(stability_df.head(10).to_string(index=False))
정리
- 특성 중요도는 모델 해석의 첫 단계입니다.
- 트리 기반 모델은 feature_importances_ 속성을 제공합니다.
- 순열 중요도는 모델에 독립적인 중요도를 제공합니다.
- 중요도를 활용하여 특성 선택을 수행할 수 있습니다.
- 상관된 특성은 중요도가 분산될 수 있습니다.
- 여러 방법의 중요도를 종합적으로 분석하는 것이 좋습니다.
다음 글 예고
다음 글에서는 SHAP으로 모델 해석하기에 대해 알아보겠습니다. SHAP 값을 통해 개별 예측의 이유를 설명하는 방법을 다룹니다.
FLAML AutoML 마스터 시리즈 #031