본문 바로가기
정보/IT 지식 정보

순차 후진 선택(SBS)으로최적의 특성 조합 찾기 [9편]

by 안다니. 2026. 3. 30.
반응형
SBS

 

13개 특성 중 몇 개를 써야 최고 성능이 나오는지, 자동으로 탐색하는 알고리즘을 구현합니다

시리즈: 머신러닝 밑바닥부터 구현하기
1~8편: 퍼셉트론 → ... → 스케일링과 규제
7편: 인코딩 · 8편: 스케일링과 규제 · 9편: 특성 선택 (완결)

왜 특성 선택이 필요한가?

Wine 데이터셋에는 13개의 특성이 있습니다. 하지만 13개 모두가 분류에 도움이 되는 것은 아닙니다. 불필요한 특성이 포함되면 오히려 모델이 노이즈를 학습하여 성능이 떨어질 수 있습니다(과적합).

8편에서 배운 L1 규제가 자동으로 불필요한 특성의 가중치를 0으로 만든다고 했습니다. 하지만 L1은 특정 모델(로지스틱 회귀 등)에서만 사용 가능합니다. 순차 후진 선택(Sequential Backward Selection, SBS)은 어떤 모델이든 적용할 수 있는 범용적인 특성 선택 방법입니다.

순차 후진 선택(SBS) 알고리즘이란?

아이디어는 단순합니다. 전체 특성에서 시작해서, 하나씩 빼가며 성능을 측정합니다. 빼도 성능이 떨어지지 않는(오히려 올라가는) 특성부터 제거합니다.

SBS 알고리즘 흐름
1. 13개 특성 전부로 모델 학습 → 정확도 측정
2. 특성 하나씩 빼보며 정확도 측정 → 빼도 가장 영향 없는 특성 제거
3. 12개 특성으로 반복 → 11개 → ... → 원하는 개수까지
4. 각 단계의 정확도를 기록 → 최적 개수 선택

scikit-learn으로 SBS 구현하기

from sklearn.feature_selection import SequentialFeatureSelector
from sklearn.linear_model import LogisticRegression

lr_fe = LogisticRegression(random_state=1)
scores = []

for n_features in range(1, 13):
    # 순차 후진 선택: n_features개까지 줄이기
    sfs = SequentialFeatureSelector(
        lr_fe,
        direction='backward',
        n_features_to_select=n_features,
        n_jobs=-1)   # 모든 CPU 코어 사용
    sfs.fit(X_train_std, y_train)

    # 선택된 특성으로 학습 후 테스트 정확도 측정
    f_mask = sfs.support_
    lr_fe.fit(X_train_std[:, f_mask], y_train)
    score = lr_fe.score(X_test_std[:, f_mask], y_test)
    scores.append(score)

핵심 파라미터는 direction='backward'(후진 방향으로 특성 제거)와 n_features_to_select(최종적으로 남길 특성 수)입니다. n_jobs=-1로 설정하면 CPU 코어를 전부 사용해서 병렬 처리합니다.

 

반응형

최적 특성 개수 찾기

특성 개수를 1개부터 12개까지 바꿔가며 정확도를 측정하고 그래프로 그립니다.

plt.plot(range(1, 13), scores, marker='o')
plt.ylabel('Accuracy')
plt.xlabel('Number of features')
plt.grid()
plt.show()
그래프 분석
특성 개수가 늘어날수록 정확도가 대체로 올라가지만, 특정 구간에서 더 적은 특성으로도 높은 정확도를 달성하는 지점이 있습니다. 이 지점이 최적의 특성 개수입니다.
적은 특성이 더 좋을 수 있는 이유
특성이 많으면 그만큼 모델이 학습해야 할 파라미터가 늘어나고, 노이즈를 학습할 가능성도 높아집니다. 불필요한 특성을 제거하면 모델이 더 단순해져서, 훈련 데이터에 과적합하지 않고 새로운 데이터에도 잘 일반화됩니다.

선택된 특성으로 최종 학습

그래프를 분석해서 최적 개수를 정한 뒤, 해당 개수로 최종 모델을 만듭니다. 여기서는 8개 특성을 선택합니다.

sfs = SequentialFeatureSelector(
    lr_fe, direction='backward',
    n_features_to_select=8, n_jobs=-1)
sfs.fit(X_train_std, y_train)

f_mask = sfs.support_
# 선택된 특성 이름 확인
df_wine.columns[1:][f_mask]
선택된 8개 특성
Malic acid, Ash, Alcalinity of ash, Flavanoids, Color intensity, Hue, OD280/OD315 of diluted wines, Proline

13개에서 5개(Alcohol, Magnesium, Total phenols, Nonflavanoid phenols, Proanthocyanins)가 제거되었습니다.
lr_fe.fit(X_train_std[:, f_mask], y_train)
print('훈련 정확도:', lr_fe.score(X_train_std[:, f_mask], y_train))
print('테스트 정확도:', lr_fe.score(X_test_std[:, f_mask], y_test))
최종 결과
훈련 정확도: 100% / 테스트 정확도: 98.1%

13개 특성을 모두 사용한 것과 거의 동일한 성능을 8개 특성만으로 달성했습니다. 모델이 더 단순해졌고 계산량도 줄었습니다.

전체 시리즈 총정리

주제 핵심 키워드
1편 퍼셉트론 가중합, 계단 함수, 선형 분리
2편 ADALINE 경사 하강법, 비용 함수, 학습률
3편 SGD 확률적 경사 하강법, 온라인 학습
4편 scikit-learn & 로지스틱 회귀 시그모이드, 확률 출력, 규제(C)
5편 SVM 마진 최대화, 커널 트릭, RBF, gamma
6편 결정 트리 & 랜덤 포레스트 지니 불순도, 앙상블, 다수결
7편 범주형 데이터 인코딩 매핑, LabelEncoder, 원-핫 인코딩
8편 스케일링과 규제 정규화, 표준화, L1/L2 규제
9편 특성 선택 순차 후진 선택, 최적 특성 개수

시리즈를 마치며

1편의 퍼셉트론에서 시작해서 9편의 특성 선택까지, 머신러닝의 기초를 코드와 함께 살펴봤습니다.

크게 두 파트로 나뉩니다. 1~6편은 "어떤 알고리즘을 쓸 것인가"에 대한 것이고, 7~9편은 "데이터를 어떻게 준비할 것인가"에 대한 것입니다. 실무에서는 후자가 더 중요한 경우가 많습니다. 아무리 좋은 알고리즘도 데이터 전처리가 잘못되면 성능이 나오지 않기 때문입니다.

이 시리즈의 내용을 이해했다면, 이후에 딥러닝(CNN, RNN, Transformer)을 배울 때도 "이건 어떤 원리의 확장인가"라는 관점에서 훨씬 빠르게 이해할 수 있을 것입니다.

머신러닝 밑바닥부터 구현하기 시리즈 [9편 · 완결]

반응형

댓글