본문으로 건너뛰기

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