Replicated

Feature Selection, Model Stacking 본문

학부/딥러닝

Feature Selection, Model Stacking

라구넹 2025. 10. 18. 17:11

Feature Selection

- 자동 또는 수동으로 피쳐를 선택하는 프로세스

- 가장 크게 기여하는 변수들을 선택

- 예측하고자 하는 변수들에 가장 크게 기여하는 변수들을 선택

- 모든 피쳐를 쓰는게 아니라, 좋은 서브셋을 선택

 

좋은 피쳐?

- 깔끔한 클래스 바운더리를 가져야 함

- 피쳐의 중요성 = 피쳐 파워 + 상호작용 파워

 

Filter method

- 모든 피쳐를 평가하고 최고 n개 피쳐 고르기

- 쉽고 빠름

- 피쳐간 인터렉션을 고려하지 않는다는 문제

 

Feature subset selction

- Foward selction : 좋은 피쳐를 추가해 나가는 방식

- Backword emimination : 안좋은 피쳐를 빼가는 방식

 

import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

df = pd.read_csv('/content/gdrive/MyDrive/Data/PimaIndiansDiabetes.csv')
print(df.head())
print(df.columns) 
df_X = df.loc[:, df.columns != 'diabetes']
df_y = df['diabetes']

model = LogisticRegression(solver='lbfgs', max_iter=3000)
scores = cross_val_score(model, df_X, df_y, cv=5)
print("Acc: "+str(scores.mean()))

 

 

필터 메소드

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

test = SelectKBest(score_func=chi2, k=df_X.shape[1])
fit = test.fit(df_X, df_y)

print(np.round(fit.scores_, 3))

f_order = np.argsort(-fit.scores_) 
sorted_columns = df.columns[f_order]

print(sorted_columns.to_list)

영향을 끼치는 순서

 

model = LogisticRegression(solver='lbfgs', max_iter=500)

for i in range(1, df_X.shape[1]+1):
  fs = sorted_columns[0:i]
  df_X_selected = df_X[fs]
  scores = cross_val_score(model, df_X_selected, df_y, cv=5)
  print(fs.tolist())
  print(np.round(scores.mean(), 4))

적용하면 pedigree는 넣으면 오히려 떨어짐

 

 

포워드 서치

from sklearn.feature_selection import SequentialFeatureSelector

model = LogisticRegression(solver='lbfgs', max_iter=500)
sfs = SequentialFeatureSelector(model, direction='forward', n_features_to_select='auto')
fit = sfs.fit(df_X, df_y)

print("Num Features: %d" % fit.n_features_in_)

fs = df_X.columns[fit.support_].tolist() # selected features
print("Selected Features: %s" % fs)

scores = cross_val_score(model, df_X[fs], df_y, cv=5)
print("Acc: "+str(scores.mean()))

가장 좋은 게 저렇게 나옴

 

 

백워드 엘리미네이션

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(solver='lbfgs', max_iter=500)
rfe = RFE(model, n_features_to_select=5)
fit = rfe.fit(df_X, df_y)

print("Num Features: %d" % fit.n_features_)

fs = df_X.columns[fit.support_].tolist() # selected features
print("Selected Features: %s" % fs)

scores = cross_val_score(model, df_X[fs], df_y, cv=5)
print("Acc: "+str(scores.mean()))

 

 

SFS

from mlxtend.feature_selection import SequentialFeatureSelector as SFS
model = LogisticRegression(solver='lbfgs', max_iter=500)

sfs1 = SFS(model,
k_features=5, # number of features
verbose=2,
scoring='accuracy',
cv=5)

sfs1 = sfs1.fit(df_X, df_y)
print( sfs1.subsets_ ) # selection process
print( sfs1.k_feature_idx_ )# selected feature index
print( sfs1.k_feature_names_ ) # selected feature name

mixtend의 SFS는 포워드 백워드 둘 가 가능

디폴트가 포워드고, forward 인자 false 주면 됨

 

scores = cross_val_score(model, df_X[list(sfs1.k_feature_names_)], df_y, cv=5)
print("Acc: "+str(scores.mean()))

* sklearn의 RFE는 모델이 coef_나 feature_importances_를 가져야 함

* KNN은 REF를 쓸 수 없음

 

피쳐 셀렉션도 cross-validation으로 평가해야 함


Voting Classifier

Simple voting

- 여러 종류의 예측 알고리즘을 이용하여 모델을 만든 뒤, 각 모델의 예측 결과로 투표(classification) 또는 평균(regression)을 구함

 

유방암 진단 예시

from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
import numpy as np

df_X, df_y = load_breast_cancer(return_X_y=True)

sc_data = StandardScaler().fit(df_X)
df_X = sc_data.transform(df_X)

데이터 준비

 

clf_lr = LogisticRegression()
clf_knn = KNeighborsClassifier(n_neighbors=1)
clf_dt = DecisionTreeClassifier(random_state=1)

clf_voting = VotingClassifier(
estimators=[('LR', clf_lr),
('KNN', clf_knn),
('DT', clf_dt)],
voting='soft')

모델들 다 넣고 보팅

* 하드는 하나의 classifier가 한 표씩 행사, 소프트는 지지 확률을 합산(권장)

 

models = [clf_lr, clf_knn, clf_dt]

for model in models:
  scores = cross_val_score(model, df_X, df_y, cv=5)
  model_name = model.__class__.__name__
  print(f"{model_name} \t : {np.mean(scores)}")

각 모델의 지지율

 

voting_scores = cross_val_score(clf_voting, df_X, df_y, cv=5)
print('Voting accuracy', np.mean(voting_scores))

오히려 보팅을 하니 떨어질 수 있다

심플 보팅은 각 모델의 성능을 최대한 끌어올린 뒤 시도


Bagging meta-estimator

- 동일한 데이터셋에 대해 샘플링을 하여 다수의 데이터셋을 구성한 뒤 단일 알고리즘으로 모델 생성

- 각 모델의 결과를 종합하여 최종 의사 결정

from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
import numpy as np

df_X, df_y = load_breast_cancer(return_X_y=True)

sc_data = StandardScaler().fit(df_X)
df_X = sc_data.transform(df_X)

model_base = KNeighborsClassifier()
scores = cross_val_score(model_base, df_X, df_y, cv=5)
print(np.mean(scores))

기본

 

model_bagging = BaggingClassifier(KNeighborsClassifier(),
    n_estimators = 100, # 모델 수
    max_samples=0.5, # 인스턴스 선택 비율
    max_features=1.0, # feature 선택 비율
    n_jobs=-1,
    random_state=123)
scores_bagging = cross_val_score(model_bagging, df_X, df_y, cv=5)
print(np.mean(scores_bagging))

bagging-meta instimator


Model stacking

- 앙상블 중 하나

- stacked generalization이라고도 함

- 여러 모델의 예측값을 인풋으로 해서 새로운 모델로 학습

- 과적합 방지를 위해 사용되기도 함

 

모델 스태킹 절차

- Level 0 : 트레이닝 데이터셋을 이용해서 sub-model 예측 결과를 생성

- Level 1 : Level0의 아웃풋 결과가 Level1의 인풋값, Level0의 아웃풋을 트레이닝 데이터로 사용하여 메타 러닝 모델을 생성

 

Level0 모델들은 되도록 다양한 예측 결과를 메타 러너에서 인풋 값으로 활용할 수 있도록 각기 다른 알고리즘을 사용하는 것이 좋음

각 서브 모델의 결과를 결합하는 메타 러너 모델은 simple linear 모델을 사용하는 것이 일반적

 

Level 0 출력값 처리

- regression의 경우 level0 출력값 그대로 인풋

- classification의 경우 그대로 쓰기보단 label probabilities 사용하는게 더 효과적

 

sklean.ensemble.StackingClassfier

- estimators : level 0에 사용할 predicator들

- final_estimator : level 1에 사용할 predicator (디폴트 LogisticRegression)

- cv : cross validiaction 값, 미제출 시 5

- stack_method

    - auto : 아래의 방법 중 하나를 적용

    - predict_proba : Level0의 Label probability를 인풋으로 사용

    - decision_function : Level0의 출력을 처리하는 함수 적용

    - predict : Level0 출력을 그대로 input으로 사용

- n_jobs : 멀티 프로세싱, -1이면 모든 코어

- passthrough

    - False: 레벨 0의 출력만 레벨 1의 학습 데이터로 사용

    - True: 레벨 0의 출력 + 오리지널 데이터셋이 레벨 1의 학습 데이터로 사용 

 

from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.ensemble import StackingClassifier
from sklearn.model_selection import cross_val_score
import numpy as np

df_X, df_y = load_breast_cancer(return_X_y=True) 
estimators = [
('rf', RandomForestClassifier(n_estimators=10, random_state=42)),
('svr', make_pipeline(StandardScaler(), LinearSVC(random_state=42, dual='auto')))]

model_1 = StackingClassifier(
estimators=estimators,
final_estimator=LogisticRegression())

scores_1 = cross_val_score(model_1, df_X, df_y, cv=5)

print(np.mean(scores_1))

예시

 

model_2 = StackingClassifier(
estimators=estimators,
final_estimator=LogisticRegression(max_iter=1000),
passthrough=True)

scores_2 = cross_val_score(model_2, df_X, df_y, cv=5)
print(np.mean(scores_2))

이런식으로 인자 바꾸기도 하고..

 

from xgboost import XGBClassifier

estimators = [
('rf', RandomForestClassifier(n_estimators=10, random_state=42)),
('svr', make_pipeline(StandardScaler(), LinearSVC(random_state=42, dual='auto'))),
('lr', LogisticRegression(max_iter=5000))]

model_3 = StackingClassifier(
estimators=estimators,
final_estimator=XGBClassifier(eval_metric='logloss', random_state=42), passthrough=True)

scores_3 = cross_val_score(model_3, df_X, df_y, cv=5)
print(np.mean(scores_3))

XGBoost를 final에 넣을 수도 있고

 

 

정리하자면

데이터셋 준비

- 피쳐 셀렉션 및 CV

- 하이퍼 파라미터 튜닝 및 CV

- 모델 비교, 보팅, 배깅, 스태킹 및 CV

- 최종 모델 빌드

의 과정을 거침

'학부 > 딥러닝' 카테고리의 다른 글

신경망 학습  (0) 2025.10.18
인공신경망 개요  (0) 2025.10.18
Classification / 결정 트리, SVM, XGBoost  (0) 2025.10.13
Classification / 앙상블, 하이퍼 파라미터 튜닝, K-fold CV, 성능 평가  (0) 2025.10.13
Regression  (0) 2025.10.12