087 자동 특성 선택
키워드: 특성 선택, feature selection
개요
특성 선택(Feature Selection)은 예측에 중요한 특성만 선택하여 모델을 단순화하고 성능을 향상시키는 과정입니다. PyCaret은 다양한 자동 특성 선택 방법을 제공합니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
pycaret[full]>=3.0
특성 선택의 목적
왜 특성 선택이 필요한가?
1. 차원의 저주 방지
- 특성 많으면 데이터 희소
- 과적합 위험 증가
2. 모델 단순화
- 해석 용이
- 예측 속도 향상
3. 노이즈 제거
- 무관한 특성 제거
- 일반화 성능 향상
4. 비용 절감
- 데이터 수집 비용
- 저장 및 처리 비용
특성 선택 방법 분류
1. Filter Methods (필터)
- 모델 독립적
- 통계적 기준
- 빠름
2. Wrapper Methods (래퍼)
- 모델 기반 평가
- 특성 부분집합 탐색
- 느림, 정확
3. Embedded Methods (임베디드)
- 모델 학습 과정에 포함
- L1/L2 정규화
- 균형적
PyCaret setup()에서 특성 선택
from pycaret.classification import *
from pycaret.datasets import get_data
# 087 데이터 로드
data = get_data('diabetes')
# 087 분산 기반 제거
clf = setup(
data,
target='Class variable',
low_variance_threshold=0.1, # 낮은 분산 특성 제거
session_id=42,
verbose=False
)
필터 방법 (Filter Methods)
분산 기반
from sklearn.feature_selection import VarianceThreshold
import pandas as pd
from pycaret.datasets import get_data
data = get_data('diabetes')
X = data.drop('Class variable', axis=1)
# 087 분산이 낮은 특성 제거
selector = VarianceThreshold(threshold=0.01)
X_selected = selector.fit_transform(X)
# 087 선택된 특성
selected_features = X.columns[selector.get_support()].tolist()
print(f"원본 특성 수: {X.shape[1]}")
print(f"선택된 특성 수: {len(selected_features)}")
print(f"선택된 특성: {selected_features}")
상관관계 기반
import pandas as pd
import numpy as np
from pycaret.datasets import get_data
data = get_data('diabetes')
X = data.drop('Class variable', axis=1)
y = data['Class variable']
# 087 타겟과의 상관관계
correlations = X.corrwith(y).abs().sort_values(ascending=False)
print("타겟과의 상관관계:")
print(correlations.round(4))
# 087 상관관계 높은 특성만 선택
threshold = 0.1
selected = correlations[correlations > threshold].index.tolist()
print(f"\n상관관계 {threshold} 이상 특성: {selected}")
상호정보량 (Mutual Information)
from sklearn.feature_selection import mutual_info_classif
import pandas as pd
# 087 상호정보량 계산
mi_scores = mutual_info_classif(X, y, random_state=42)
mi_df = pd.DataFrame({
'feature': X.columns,
'mi_score': mi_scores
}).sort_values('mi_score', ascending=False)
print("상호정보량:")
print(mi_df.round(4))
# 087 상위 N개 선택
top_n = 5
top_features = mi_df.head(top_n)['feature'].tolist()
print(f"\n상위 {top_n}개: {top_features}")
SelectKBest
from sklearn.feature_selection import SelectKBest, f_classif
import pandas as pd
# 087 F-통계량 기반 상위 K개 선택
selector = SelectKBest(f_classif, k=5)
X_selected = selector.fit_transform(X, y)
# 087 선택된 특성
selected_features = X.columns[selector.get_support()].tolist()
print(f"F-score 기반 상위 5개: {selected_features}")
# 087 점수 확인
scores_df = pd.DataFrame({
'feature': X.columns,
'score': selector.scores_,
'pvalue': selector.pvalues_
}).sort_values('score', ascending=False)
print("\nF-score:")
print(scores_df.round(4))
래퍼 방법 (Wrapper Methods)
RFE (Recursive Feature Elimination)
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
# 087 기본 모델
estimator = RandomForestClassifier(n_estimators=100, random_state=42)
# 087 RFE: 재귀적 특성 제거
rfe = RFE(
estimator=estimator,
n_features_to_select=5, # 선택할 특성 수
step=1 # 한 번에 제거할 특성 수
)
rfe.fit(X, y)
# 087 결과
rfe_df = pd.DataFrame({
'feature': X.columns,
'selected': rfe.support_,
'ranking': rfe.ranking_
}).sort_values('ranking')
print("RFE 결과:")
print(rfe_df)
selected_features = X.columns[rfe.support_].tolist()
print(f"\n선택된 특성: {selected_features}")
RFECV (교차 검증 포함)
from sklearn.feature_selection import RFECV
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
import matplotlib.pyplot as plt
# 087 교차 검증 기반 RFE
rfecv = RFECV(
estimator=RandomForestClassifier(n_estimators=100, random_state=42),
step=1,
cv=StratifiedKFold(5),
scoring='accuracy',
n_jobs=-1
)
rfecv.fit(X, y)
print(f"최적 특성 수: {rfecv.n_features_}")
print(f"선택된 특성: {X.columns[rfecv.support_].tolist()}")
# 087 성능 vs 특성 수
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(rfecv.cv_results_['mean_test_score']) + 1),
rfecv.cv_results_['mean_test_score'])
plt.xlabel('Number of Features')
plt.ylabel('CV Accuracy')
plt.title('RFECV: Optimal Number of Features')
plt.axvline(x=rfecv.n_features_, color='r', linestyle='--', label=f'Optimal: {rfecv.n_features_}')
plt.legend()
plt.savefig('rfecv.png', dpi=150)
임베디드 방법 (Embedded Methods)
L1 정규화 (Lasso)
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
import pandas as pd
# 087 스케일링
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 087 L1 정규화 로지스틱 회귀
lasso = LogisticRegression(penalty='l1', solver='saga', C=0.1, random_state=42, max_iter=1000)
lasso.fit(X_scaled, y)
# 0이 아닌 계수 = 선택된 특성
lasso_df = pd.DataFrame({
'feature': X.columns,
'coefficient': lasso.coef_[0]
})
selected = lasso_df[lasso_df['coefficient'] != 0]['feature'].tolist()
print(f"L1 선택 특성 ({len(selected)}개): {selected}")
SelectFromModel
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
# 087 랜덤 포레스트 기반 선택
rf = RandomForestClassifier(n_estimators=100, random_state=42)
selector = SelectFromModel(rf, threshold='median') # 중앙값 이상
selector.fit(X, y)
# 087 선택된 특성
selected_features = X.columns[selector.get_support()].tolist()
print(f"RF 기반 선택 ({len(selected_features)}개): {selected_features}")
# 087 임계값 조정
selector_top = SelectFromModel(rf, threshold='1.5*mean') # 평균의 1.5배 이상
selector_top.fit(X, y)
top_features = X.columns[selector_top.get_support()].tolist()
print(f"상위 특성 ({len(top_features)}개): {top_features}")
PyCaret 통합 워크플로우
from pycaret.classification import *
from pycaret.datasets import get_data
data = get_data('diabetes')
# 1. 기본 setup (모든 특성)
clf_all = setup(data, target='Class variable', session_id=42, verbose=False)
rf_all = create_model('rf')
# 087 특성 선택 후 성능 비교
from sklearn.feature_selection import SelectKBest, f_classif
# 087 상위 5개 특성만 선택
X = data.drop('Class variable', axis=1)
y = data['Class variable']
selector = SelectKBest(f_classif, k=5)
selector.fit(X, y)
selected = X.columns[selector.get_support()].tolist()
# 087 선택된 특성으로 새 데이터
data_selected = data[selected + ['Class variable']]
# 2. 선택된 특성으로 setup
clf_selected = setup(data_selected, target='Class variable', session_id=42, verbose=False)
rf_selected = create_model('rf')
print(f"\n전체 특성: {X.shape[1]}개")
print(f"선택 특성: {len(selected)}개")
자동 특성 선택 파이프라인
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
# 087 파이프라인 구성
pipeline = Pipeline([
('scaler', StandardScaler()),
('selector', SelectKBest(f_classif, k=5)),
('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])
# 087 교차 검증
scores = cross_val_score(pipeline, X, y, cv=5, scoring='accuracy')
print(f"CV 정확도: {scores.mean():.4f} ± {scores.std():.4f}")
특성 선택 가이드
데이터 상황별 권장 방법:
대용량 데이터:
- Filter (빠름)
- 분산, 상관관계
적은 데이터:
- RFECV (안정적)
- 교차 검증 필수
고차원:
- L1 정규화
- SelectFromModel
해석 중요:
- 도메인 지식 + Filter
- 명확한 기준
성능 최우선:
- RFECV
- 여러 방법 비교
정리
- 특성 선택: 모델 단순화, 성능 향상
- Filter: 빠름, 모델 독립적
- Wrapper (RFE): 정확, 느림
- Embedded (L1): 학습 과정에 포함
- 여러 방법 비교 후 결정 권장
다음 글 예고
다음 글에서는 불균형 데이터 처리를 다룹니다.
PyCaret 머신러닝 마스터 시리즈 #087