본문 바로가기
파이썬 라이브러리를 활용한 머신러닝

Automatic Feature Selection

by 지식광부키우기 2019. 12. 9.

 

개요

 

새로운 특성을 만드는 방법이 많으므로, 데이터의 차원이 원복 특성의 수 이상으로 증가하기 쉽습니다. 

 

그러나, 특성이 더 추가되면 모델은 더 복잡해지고 과대적합될 가능성도 높아집니다.

 

가장 유용한 특성남 선택하고 나머지는 무시해서 특성의 수를 줄이는 것이 좋습니다. 

 

이렇게 하면 모델이 간단해지고 일반화 성능이 올라갑니다. 

 

데이터를 훈련 세트와 테스트 세트로 나눈 다음 훈련 데이터만 특성 선택에 사용해야 합니다. 

 

 

특성 추출 vs 특성 선택 (Feature Extraction vs Feature Selection)

 

특성 추출 (Feature Extraction)은 특성을 결합하여 더 유용한 특성을 만듭니다. (e.g. PCA)

 

특성 선택 (Feature Selection)은 가지고 있는 특성 중에서 훈련에 가장 유용한 특성을 선택합니다. 

 

특성 선택을 선호할 때?

 

특성을 얻는 비용이 높을 때

 

본래 특성의 표현을 유지하려고 할 때 (해석력)

 

 

특성 선택 전략 (Feature Selection Strategies)

 

Filter Methods : 적용하려는 학습 알고리즘에 상관없이 전처리 과정으로 특성을 선택합니다. 

 

Wrapper Methods : 특성의 수가 각기 다른 일련의 모델을 만들어 예측력이 높은 모델의 특성들을 선택합니다. 

 

Embedded Methods : 지도 학습 머신러닝 모델을 사용하여 특성의 중요도를 평가해서 가장 중요한 특성들만 선택합니다. (라쏘 회귀, 결정 트리, 랜덤 포레스트 등)

 

그림1

 

 

Filter Methods

 

Filter Methods : 적용하려는 학습 알고리즘에 상관없이 전처리 과정으로 특성을 선택합니다.

 

개개의 특성과 타깃 사이에 중요한 통계적 관계가 있는지를 계산합니다. 

 

그런 다음 깊게 관련되어 이싸고 판단되는 특성을 선택합니다.

 

따라서 다른 특성과 깊게 연관된 특성은 선택되지 않을 것입니다.

 

일변량 분석은 계산이 매우 빠르고 평가를 위해 모델을 만들 필요가 없습니다.

 

한편으로 이 방식은 특성을 선택한 후 적용하려는 모델에 상관없이 사용할 수 있습니다. 

 

 

Breast Cancer 데이터셋 - Filter Methods

 

from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
cancer.data, cancer.target, stratify=cancer.target, random_state=66)

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
X_train.shape

(426, 30)

 

데이터 로드 후 훈련 세트와 테스트 셋으로 나누고 스케일링 해주었습니다.

 

 

clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train, y_train)

 

모델을 만든 후

 

 

y_train_hat = clf.predict(X_train)
print('train accuracy :', accuracy_score(y_train, y_train_hat))
y_test_hat = clf.predict(X_test)
print('test accuracy :', accuracy_score(y_test, y_test_hat))

train accuracy : 0.9882629107981221

test accuracy : 0.9440559440559441

 

특성 선택에 별다른 제재를 가하지 않은 결과입니다.

 

 

from sklearn.feature_selection import SelectKBest, f_classif
select = SelectKBest(f_classif, k=20)
select.fit(X_train, y_train)
select.scores_

그림2

 

일변량 분석을 통해 F-값을 나타냈습니다.

 

 

from sklearn.feature_selection import SelectKBest, mutual_info_classif
select = SelectKBest(mutual_info_classif, k=20)
select.fit(X_train, y_train)
select.scores_

그림3

 

상호 정보까지 고려하여 F-값을 나타냈습니다.

 

 

from sklearn.feature_selection import SelectKBest, f_classif
select = SelectKBest(f_classif, k=20)
select.fit(X_train, y_train)
X_train_selected = select.transform(X_train)
X_test_selected = select.transform(X_test)

 

일변량 분석으로 특성 수를 20개까지 선택했습니다.

 

 

clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train_selected, y_train)
y_train_hat = clf.predict(X_train_selected)
print('train accuracy :', accuracy_score(y_train, y_train_hat))
y_test_hat = clf.predict(X_test_selected)
print('test accuracy :', accuracy_score(y_test, y_test_hat))

train accuracy : 0.9859154929577465

test accuracy : 0.958041958041958

 

훈련 정확도가 아주 약간 감소하였고 테스트 정확도가 상승하였습니다.

 

 

from sklearn.feature_selection import SelectKBest, mutual_info_classif
select = SelectKBest(mutual_info_classif, k=20)
select.fit(X_train, y_train)
X_train_selected = select.transform(X_train)
X_test_selected = select.transform(X_test)

 

상호 정보를 고려한 특성을 20개 택하였습니다.

 

 

clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train_selected, y_train)
y_train_hat = clf.predict(X_train_selected)
print('train accuracy :', accuracy_score(y_train, y_train_hat))
y_test_hat = clf.predict(X_test_selected)
print('test accuracy :', accuracy_score(y_test, y_test_hat))

train accuracy : 0.9906103286384976

test accuracy : 0.965034965034965

 

훈련 정확도와 테스트 정확도 모두 상승하였습니다.

 

 

Wrapper Methods

 

Wrapper Methods : 특성의 수가 각기 다른 일련의 모델을 만들어 예측력이 높은 모델의 특성들을 선택합니다. 

 

특성의 수가 다른 일련의 모델을 만듭니다.

 

Wrapper methdes는 특성과 사용된 모델의 상호 작용이며, filter methods보다 더 높은 예측 정확도를 보입니다.

 

Filter/embedded 방법보다 계산 비용이 훨씬 많이 듭니다.

 

 

Exhaustive search (완전 탐색) : 특성의 모든 가능한 결합을 계산합니다. ($2^{d} - 1) -> 불가능

 

Sequential methods (순차 탐색) : 예측 정확도를 최대화하는 특성들을 선택하기 위해 하나씩 추가하거나 제거합니다.

 

Forward selection (전진 선택법) : 특성을 하나도 선택하지 않은 상태로 시작해서 어떤 종료 조건에 도달할 때까지 하나씩 추가하는 방법입니다.

 

Backward selection (후진 선택법) : 모든 특성을 가지고 시작해서 어떤 종료 조건이 될 때까지 특성을 하나씩 제거해가는 방법입니다.

 

Stochastic methods (확률론적 방법) : local optima를 피하기 위해 탐색 절차에서 임의적으로 택합니다.

 

Genetic algorithm (GA),  particle swarm optimization, ant colony optimization, simulated annealing 같은 메타휴리스틱 최적 알고리즘에서 주로 사용합니다. 

 

 

Embedded Methods

 

Embedded Methods : 지도 학습 머신러닝 모델을 사용하여 특성의 중요도를 평가해서 가장 중요한 특성들만 선택합니다. (라쏘 회귀, 결정 트리, 랜덤 포레스트 등)

 

특성 선택을 위한 모델은 각 특성의 중요도를 측정하여 순서를 매길 수 있어야 합니다.

 

결정 트리와 이를 기반으로 한 모델은 각 특성의 중요도가 담겨 있는 feature_importances_ 속성을 제공합니다.

 

선형 모델 계수의 절댓값도 특성의 중요도를 재는 데 사용할 수 있습니다.

 

지도 학습 모델은 최종적으로 사용할 지도 학습 모델과 같을 필요는 없습니다. 

 

 

Breast Cancer 데이터셋 - SelectFromModel

 

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
fmodel = RandomForestClassifier()
select = SelectFromModel(fmodel, threshold="mean")
select.fit(X_train, y_train)
X_train_selected = select.transform(X_train)
X_test_selected = select.transform(X_test)
select.get_support()

그림4

 

get_support 메서드는 선택한 특성을 불린 값으로 표시해주어 어떤 특성이 선택되었는지 확인할 수 있습니다. 

 

중요도를 지정한 임계치보다 큰 모든 특성을 선택했습니다. 

 

 

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LinearRegression
fmodel = LinearRegression()
select = SelectFromModel(fmodel, threshold="0.5*mean")
select.fit(X_train, y_train)
X_train_selected = select.transform(X_train)
X_test_selected = select.transform(X_test)
select.get_support()

그림5

 

선형 회귀로 선택한 특성들입니다.

 

 

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
fmodel = RandomForestClassifier()
fmodel.fit(X_train, y_train)
fmodel.feature_importances_

그림6

 

feature_importances_ 메서드로 중요도를 수치로 볼 수 있습니다

 

 

select = SelectFromModel(fmodel,prefit=True, threshold="mean")
X_train_selected = select.transform(X_train)
X_test_selected = select.transform(X_test)
select.get_support()

그림7

 

중요도를 지정한 임계치보다 큰 모든 특성을 선택했습니다. 

 

 

결론

 

머신러닝 알고리즘에 어떤 입력값을 넣을지 확신이 안 선다면 특성 자동 선택이 도움될 수 있습니다.

 

또 예측 속도를 높이거나 해석하기 더 쉬운 모델을 만드는 데 필요한 만큼 특성의 수를 줄이는 데 효과적입니다.

 

대부분 실전에서는 특성 선택이 큰 성능 향상을 끌어내진 못하는 것 같습니다.

 

그러나 특성 선택은 머신러닝 기술자에게 여전히 유용한 도구입니다.

 

 

파이썬 라이브러리를 활용한 머신러닝 책과 성균관대학교 강석호 교수님 수업 내용을 바탕으로 요약 작성되었습니다.

댓글