
13개 특성 중 몇 개를 써야 최고 성능이 나오는지, 자동으로 탐색하는 알고리즘을 구현합니다
1~8편: 퍼셉트론 → ... → 스케일링과 규제
7편: 인코딩 · 8편: 스케일링과 규제 · 9편: 특성 선택 (완결)
왜 특성 선택이 필요한가?
Wine 데이터셋에는 13개의 특성이 있습니다. 하지만 13개 모두가 분류에 도움이 되는 것은 아닙니다. 불필요한 특성이 포함되면 오히려 모델이 노이즈를 학습하여 성능이 떨어질 수 있습니다(과적합).
8편에서 배운 L1 규제가 자동으로 불필요한 특성의 가중치를 0으로 만든다고 했습니다. 하지만 L1은 특정 모델(로지스틱 회귀 등)에서만 사용 가능합니다. 순차 후진 선택(Sequential Backward Selection, 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]
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))
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편 · 완결]
'정보 > IT 지식 정보' 카테고리의 다른 글
| ROC 곡선과 PR 곡선 완전 이해 — 분류 모델의 진짜 성능 읽기 [2편] (0) | 2026.03.31 |
|---|---|
| 교차 검증과 혼동 행렬이란? 모델 성능을 제대로 평가하는 법 [1편] (0) | 2026.03.31 |
| 정규화 vs 표준화, 그리고 L1 규제데이터 스케일링의 모든 것 [8편] (0) | 2026.03.30 |
| 범주형 데이터 인코딩이란?매핑부터 원-핫 인코딩까지 완전 정리 [7편] (0) | 2026.03.27 |
| 결정 트리와 랜덤 포레스트란?트리 기반 분류 완전 정리 [6편] (0) | 2026.03.27 |
댓글