오늘 할 일: 끝내주게 숨쉬기
article thumbnail

머신러닝으로 타겟을 예측하기 위해 수십, 수백개의 변수를 준비했습니다. 이 많은 변수들을 전부 머신러닝에 인풋 변수로 넣으면 최고의 성능이 나올까요? 항상 그렇지는 않습니다. 타겟과 연관성이 높은 변수도 있지만, 그 중에는 타겟을 예측하는 데에 혼선을 주는 변수들도 있을 수 있기 때문입니다. 게다가 입력변수가 너무 많으면 학습하는 속도도 느려지겠죠. 수집한 많은 변수들 중, 타겟을 예측할 때 유의미하게 사용될 수 있는 변수들을 분석가가 하나씩 살펴보며 취사선택할 수도 있지만 변수가 너무 많은 경우는 수작업이 어렵습니다.. 이때 사용하는 방법으로는 RFE(Recursive Feature Elimination)이 있습니다.

 

RFE (Recursive Feature Elimination)

RFE는 변수 선택 방법으로, 원하는 개수의 변수들이 남을 때까지 학습을 반복하며 유의미하지 않은 변수들을 제거해나가는 Backward 방식입니다. 분석가가 변수 선택을 위해 사용하려는 알고리즘을 선택하면, 먼저 모든 입력변수를 사용해 모델을 학습하고 변수들의 변수 중요도(feature importance)를 계산합니다. 그리고 변수 중요도가 낮은 변수들을 이후 단계에서 제거하는 방식이죠. 그렇게 지정한 개수만큼 변수가 남을 때까지 반복합니다.

 

from sklearn.datasets import make_classification
from sklearn.feature_selection import RFE, RFECV
from lightgbm import LGBMClassifier
import matplotlib.pyplot as plt
X, y = make_classification(n_samples=1000, n_features=200, random_state=1234)
display(X.shape, y.shape)
(1000, 200)
(1000,)

파이썬 실습을 위해 사이킷런 라이브러리와 lightgbm 라이브러리를 불러옵니다.(Python 3.8.6 사용) RFE를 적용할 데이터는 make_classification 함수를 사용하여 만들었습니다. 샘플 수는 1000개, 변수 수는 200개인 임의의 데이터이고, 타겟은 0 또는 1인 이진 분류용 데이터입니다.

 

clf = LGBMClassifier(random_state=1234, n_estimators=100, learning_rate=0.01)
selector = RFE(clf, n_features_to_select=50, step=10)
selector = selector.fit(X, y)

LGBMClassifier으로 모델을 먼저 정의한 후, RFE를 적용합니다. 위 코드를 실행하면 전체 변수 200개에서 중요하지 않은 변수들을 10개씩 줄여가며 변수가 50개 남을 때까지 학습을 반복할 수 있습니다.

  • n_features_to_select: 최종 선택할 변수 개수
  • step: 매 단계마다 제거할 변수 개수

fit을 적용한 후 RFE를 통해 선택된 변수가 무엇인지는 selector.support_를 통해 확인할 수 있습니다. 전체 변수에 대해 선택된 경우 True, 선택되지 않은 경우는 False를 반환합니다. 이후 모델링에서 True에 해당하는 변수들을 활용하는 것이죠. 

selector.support_
array([ True, False, False, False, False,  True, False, False, False,
       False, False, False, False, False, False, False, False,  True,
        True, False, False,  True,  True,  True, False, False, False,
       False, False,  True, False,  True, False, False, False, False,
       False, False, False, False, False,  True, False, False,  True,
       False, False,  True, False, False,  True, False,  True, False,
       False, False, False,  True, False,  True, False, False, False,
       False, False,  True, False, False,  True, False,  True,  True,
        True, False, False, False,  True, False, False, False, False,
        True, False, False, False, False,  True,  True, False, False,
       False,  True, False, False, False,  True, False, False, False,
       False,  True, False, False, False,  True,  True,  True, False,
       False, False, False, False,  True, False, False, False, False,
       False, False, False, False, False,  True, False, False, False,
       False, False, False, False, False, False, False, False,  True,
       False,  True, False,  True, False, False, False, False, False,
       False, False, False, False,  True, False,  True, False, False,
       False, False,  True, False, False, False, False, False, False,
       False,  True, False, False, False, False, False,  True, False,
       False,  True, False, False,  True, False, False, False,  True,
       False,  True, False,  True,  True, False,  True, False,  True,
       False, False, False, False, False, False, False,  True, False,
       False, False])

 

RFECV (Recursive Feature Elimination with Cross Validation)

위에서 코드로 확인한 바와 같이 RFE를 수행할 때는 선택할 변수의 개수를 지정해줘야 합니다. 분석가가 그 개수를 정하기가 어렵다는 단점이 있죠. 이 문제를 해결하기 위해 RFE 대신 RFECV를 사용할 수 있습니다. RFE와 마찬가지로 RFECV는 낮은 변수 중요도를 갖는 변수들을 제거하는 데, 변수를 제거하며 학습할 때마다 Cross Validation을 활용해 성능을 계산합니다. 그 개수의 변수들을 활용해 모델을 학습했더니 성능이 어땠는지 확인하는 것이죠. 변수를 많이 썼더니 오히려 성능이 떨어졌다던지, 몇 개의 변수를 썼더니 성능이 제일 좋았는지 등을 확인할 수 있습니다. 실험이 끝나면 선택된 변수들을 머신러닝을 학습시킬 때 활용할 수 있겠죠.

 

clf = LGBMClassifier(random_state=1234, n_estimators=100, learning_rate=0.01)
min_features_to_select = 30
step = 10
selector = RFECV(clf, step=step, cv=5, min_features_to_select=min_features_to_select)
selector = selector.fit(X, y)

RFE와 마찬가지로, LGBMClassifier으로 모델을 먼저 정의한 후, RFECV를 적용합니다. 위 코드를 통해 전체 변수 200개에서 중요하지 않은 변수들을 10개씩 줄여가며 학습을 반복하고, 각 단계마다 CV로 성능을 평가할 수 있습니다. 매 단계마다 변수를 제거하다가 30개가 남았을 때는 반복을 중단하도록 설정했습니다.

  • min_features_to_select: 최소한으로 선택할 변수 개수
  • step: 매 단계마다 제거할 변수 개수
  • cv: Cross Validation시 사용할 폴드 개수

역시 RFECV를 통해 선택된 변수가 무엇인지는 selector.support_를 통해 확인할 수 있으며, 최적으로 선택된 변수 개수는 60개임을 알 수 있습니다.

selector.support_.sum()
60

 

plt.figure()
plt.xlabel("Number of features selected")
plt.ylabel("Cross validation score (accuracy)")
plt.plot(
    range(min_features_to_select, len(selector.grid_scores_)*step + min_features_to_select, step),
    selector.grid_scores_,
)

 

선택한 변수 개수마다의 성능을 그래프로 확인해보았습니다. 변수를 100개 이상 선택하여 학습했을 때와 60개만 선택했을 때의 성능이 동일하기 때문에, 최적의 변수 개수는 60개라고 판단할 수 있습니다.

 

참고

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html#sklearn.feature_selection.RFE

 

sklearn.feature_selection.RFE

Examples using sklearn.feature_selection.RFE: Recursive feature elimination Recursive feature elimination,

scikit-learn.org

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFECV.html?highlight=rfecv 

 

sklearn.feature_selection.RFECV

Examples using sklearn.feature_selection.RFECV: Recursive feature elimination with cross-validation Recursive feature elimination with cross-validation,

scikit-learn.org