Feature Selection
모델을 구성하는 주요 피처들을 선택
- 불필요한 다수의 피처들로 인해 모델 성능을 떨어뜨릴 가능성 제거
- 설명 가능한 모델이 될 수 있도록 피처들을 선별
- 다수의 피처로 모델 학습시 과적합 이슈 발생(차원의 저주)
●Feature Selection 하는 방법
-피처값의 분포: 특정 피처의 값이 딱 하나라면, 이 피처가 있으나 없으나 피처와 타겟값 간의 패턴에 변별력이 없음
-결측값이 많은 피처: 결측값이 많은 피처는 제거 대상이 될 수 있음
-피처간 높은 상관도: '데이터 전처리-변수 분포 문제- 특징 간 상관성 제거' 참고
-결정값과의 독립성등을 고려: '데이터 전처리-차원의 저주 문제' 참고
-모델의 피처 중요도 기반: RFE, SelectFromModel, Permutation importance
○ RFE(Recursive Feature Elimination)
- 모델 최초 학습 후 feature 중요도 선정
- feature 중요도가 낮은 속성들을 차례로 제거해 가면서 반복적으로 학습/평가를 수행하여 최적 feature 추출
- 수행시간이 오래 걸리고, 낮은 속성들을 제거해 나가는 메커니즘이 정확한 feature selection을 찾는 목표에 정확히 부합하지 않을 수 있음
# 실습을 위한 임의의 분류용 데이터 생성
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=25, n_informative=3,
n_redundant=2, n_repeated=0, n_classes=8,
n_clusters_per_class=1, random_state=0)
# 피처들을 데이터프레임 형태로 만들어보자
import pandas as pd
columns_list = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7', 'col8', 'col9', 'col10', 'col11', 'col12', 'col13',
'col14', 'col15', 'col16', 'col17', 'col18', 'col19', 'col20', 'col21', 'col22', 'col23', 'col24', 'col25']
df_X = pd.DataFrame(X, columns=columns_list)
# RFE
from sklearn.feature_selection import RFE
from sklearn.svm import SVC # 사용할 모델
svc = SVC(kernel='linear')
rfe = RFE(estimator=svc, n_features_to_select=5, step=1) # step=1: 하나씩 피처 제거, n_features_to_select=5: 5개 피처를 선택
rfe.fit(X, y)
print(rfe.support_) # 선택된 피처는 True로 반환
print('선택된 피처:', df_X.columns[rfe.support_])
# 선택된 피처를 통한 최종 데이터프레임 생성
feature_selection = df_X.columns[rfe.support_]
df_X = df_X[feature_selection]
df = df_X # 데이터프레임 이름 변경
df['target'] = y
df.head()
○ RFECV(Recursive Feature Elimination with Cross Validation)
- RFECV는 RFE와 로직은 똑같지만, 각 feature 개수마다 교차검증을 활용해 각 feature 개수별 성능을 평균내어 가장 높은 성능을 가지는 feature 개수에 해당하는 feature들을 최종 feature selection 결과로 사용
→ 몇 개의 피처가 최적일지 알 수 있음
# 실습을 위한 임의의 분류용 데이터 생성
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=25, n_informative=3,
n_redundant=2, n_repeated=0, n_classes=8,
n_clusters_per_class=1, random_state=0)
# 피처들을 데이터프레임 형태로 만들어보자
import pandas as pd
columns_list = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7', 'col8', 'col9', 'col10', 'col11', 'col12', 'col13',
'col14', 'col15', 'col16', 'col17', 'col18', 'col19', 'col20', 'col21', 'col22', 'col23', 'col24', 'col25']
df_X = pd.DataFrame(X, columns=columns_list)
# RFECV
from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold
from sklearn.svm import SVC # 사용할 모델
svc = SVC(kernel='linear')
rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(3), scoring='accuracy')
rfecv.fit(X, y)
# 몇 개의 피처가 최적일지 교차검증 성능 시각화
import matplotlib.pyplot as plt
plt.figure()
plt.xlabel('Number of features selected')
plt.ylabel('Cross validation score')
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show() # cv를 3으로 해서 3개의 그래프가 나옴
# 0~5 사이에 특정 값이 최적의 피처 개수인듯
print('최적 피처 개수:', rfecv.n_features_)
print('선택된 피처:', df_X.columns[rfecv.support_])
# 선택된 피처를 통한 최종 데이터프레임 생성
feature_selection = df_X.columns[rfecv.support_]
df_X = df_X[feature_selection]
df = df_X # 데이터프레임 이름 변경
df['target'] = y
df.head()
○ SelectFromModel
- 모델 최초 학습 후 선정된 feature 중요도에 따라 평균/중앙값 등의 특정 비율 이상인 feature들을 선택
(이 비율은 threshold로 지정)
# 실습을 위한 데이터 세트
from sklearn.datasets import load_diabetes
diabetes = load_diabetes()
X = diabetes.data
y = diabetes.target
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LassoCV # 사용할 모델
lasso = LassoCV()
lasso.fit(X,y) # 모델 학습
# 회귀계수 절대값 시각화
importance = np.abs(lasso.coef_)
plt.bar(height=importance, x=diabetes.feature_names)
plt.title('feature importances via coefficients')
plt.show()
# selectfrommodel
from sklearn.feature_selection import SelectFromModel
threshold = np.sort(importance)[-3] + 0.01 # 회귀계수가 3번째로 큰 값에 0.01을 더해서 threshold 지정하기로 결정
sfm = SelectFromModel(lasso, threshold=threshold)
sfm.fit(X,y)
print(sfm.threshold_) # threshold 값
print(sfm.get_support()) # 선택된 피처는 True로 반환
print('선택된 피처:', np.array(diabetes.feature_names)[sfm.get_support()])
# 다른 threshold 지정해보기
sfm = SelectFromModel(lasso, threshold='1.5 * median')
sfm.fit(X, y)
print(sfm.threshold_)
print(sfm.get_support())
print('선택된 피처:', np.array(diabetes.feature_names)[sfm.get_support()])
SelectFromModel Reference)
https://bizzengine.tistory.com/163
Automatic Feature Selection
개요 새로운 특성을 만드는 방법이 많으므로, 데이터의 차원이 원복 특성의 수 이상으로 증가하기 쉽습니다. 그러나, 특성이 더 추가되면 모델은 더 복잡해지고 과대적합될 가능성도 높아집니
bizzengine.tistory.com
사이킷런의 Recursive Feature Elimination이나 SelectFromModel의 경우 트리기반의 분류에서는 Feature importance, 회귀에서는 회귀 계수를 기반으로 반복적으로 모델 평가하면서 피처들을 선택하는 방식인데, 이런 방식의 Feature Selection은 오히려 모델의 성능을 떨어뜨릴 가능성이 높다. 그러니까 정확하지 않은 feature selection 방법이다.
→ Permutation importance가 보다 정확한 방식
이어서 permutation importance 정리 및 실습 진행
Reference)
'파이썬 머신러닝 완벽가이드 > [4장] 분류' 카테고리의 다른 글
Feature Selection의 이해(2) (0) | 2023.03.06 |
---|---|
스태킹 앙상블 (0) | 2023.02.27 |
캐글 신용카드 사기 검출 (0) | 2023.02.25 |
캐글 신용카드 사기 검출(log 변환, 이상치 제거, SMOTE 오버샘플링 기초지식) (0) | 2023.02.24 |
캐글 산탄데르 고객 만족 예측 (0) | 2023.02.23 |