1. 코드의 목적과 역할 분석
목적 :
소프트 보팅(Soft Voting) 이라는 앙상블 기법을 활용해 분류 모델의 성능을 향상시키는 것
여러 개의 분류 모델 ( Logistic Regression, Decision Tree, SVM )을 조합하여 단일 모델보다 일반화 성능을 높이는 것을 목적으로 함
개별 모델이 가지는 약점을 서로 보완하면서 안정적인 예측 결과를 얻음
역할 :
VotingClassifier를 활용한 소프트 보팅 예제 구현
Iris 데이터셋을 대상으로 모델을 학습·평가하며, 앙상블 기법의 효과를 실습
2. 필수 라이브러리
라이브러리 및 모듈 역할
| from sklearn.ensemble import VotingClassifier | 여러 모델 예측 결합을 위한 앙상블 클래스 |
| from sklearn.linear_model import LogisticRegression | 로지스틱 회귀 분류기 |
| from sklearn.tree import DecisionTreeClassifier | 결정 트리 분류기 |
| from sklearn.svm import SVC | 서포트 벡터 머신 분류기 (확률 예측 옵션 사용) |
| from sklearn.datasets import load_iris | 예제용 Iris 꽃붓 데이터셋 로드 함수 |
| from sklearn.model_selection import train_test_split | 학습/테스트 데이터 분리 함수 |
3. 코드 해석
# softvoting.py
# 소프트 보팅 (실무에서는 소프트보팅을 많이 씀)
# 라이브러리
from sklearn.ensemble import VotingClassifier # 3개의 모델 앙상블
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# train / test 분리
X, y = load_iris(return_X_y=True) # 입력(X), 타겟(y)
# 입력 데이터 X (꽃받침, 꽃잎의 길이와 너비 등 4개 특성), 출력 타겟 y(꽃 종류 3가지 클래스)
X_train, X_test, y_train, y_test = \
train_test_split(X, y, test_size=0.25, random_state=42)
# 개별 분류 모델 정의
lr = LogisticRegression() # 로지스틱 회귀 모델 : 선형적 경계를 찾아 데이터를 분류하는 간단하고 해석이 쉬운 모델
dt = DecisionTreeClassifier() # 결정 트리 모델 : 데이터를 분할 기준으로 계층적으로 분류하는 모델 (직관적, 성능 우수)
svm = SVC(probability=True) # SVM 모델 (확률 예측 가능하도록 설정) : 데이터를 나누는 최적의 경계를 찾는 모델 (비선형 문제에 강력한 성능)
# 정의한 3개의 분류기를 소프트보팅으로 결합한 Voting Classifier 생성
voting_clf = VotingClassifier(
estimators = [('lr', lr), ('dt', dt), ('svm', svm)], # 각 모델에 이름 부여
voting = 'soft' # 소프트보팅 사용
)
'''
모델1 (LogisticRegression): 클래스 A 70%, 클래스 B 30%
모델2 (DecisionTree): 클래스 A 60%, 클래스 B 40%
모델3 (SVC): 클래스 A 80%, 클래스 B 20%
→ 평균: 클래스A(70%), 클래스B(30%) → 최종 클래스는 클래스A
'''
# 분류기 학습 : 소프트 보팅 앙상블 모델에 학습 데이터를 제공하여 모델 학습 진행
voting_clf.fit(X_train, y_train)
# 모델 평가 / 정확도 출력
print('정확도: ', voting_clf.score(X_test, y_test))
4. 향후 개선, 확장 방향
현재 예제 코드는 각 분류기를 생성할 때 별도의 하이퍼파라미터를 지정하지 않고 모두 기본값, 데이터 전처리 등 어떤 추가 기법도 적용하지 않은 순수 기본 설정 상태임
1. 하이퍼 파라미터 튜닝
- 모델마다 성능에 민감하게 작용하는 설정값이 있음
- 최적의 파라미터 조합을 찾아 과적합, 과소적합을 최소화하고 일반화 성능을 최대화 해보기
2. 다양한 모델 추가
k-NN, 랜덤포레스트, XGBoost 등 서로 다른 학습 방식의 모델을 같이 실험해보기
모델마다 장단점이 달라서 특정 데이터 셋에서 더 잘맞는 알고리즘을 찾거나 앙상블 성능을 높이기 위함
3. 스태킹 기법 도입
- 1차 모델들의 예측 결과를 입력으로 2차 모델을 학습시키는 방식
- 여러 모델의 예측 패턴을 메타 모델이 종합 학습해, 단순 보팅보다 더 정교한 앙상블 예측력을 얻기 위함
4. 교차 검증
- 데이터를 여러 겹으로 나눠, 각 겹을 한 번씩 검증 세트로 사용하면서 모델을 평가하기
- 특정 분할에 의한 성능 편향을 줄이고, 더 안정적이고 신뢰할 만한 모델 성능 추정치를 얻기 위함
5. 다중 클래스 불균형 처리
- 클래스 비율이 극도로 치우친 경우, 소수 클래스에 대한 예측력이 크게 떨어짐
- class-weight = 'balanced' 등으로 가중치를 조정해 소수 클래스를 더 잘 학습시켜, 편향 없는 분류 성능을 확보하기 위해서
5. 정확도 1.0?
sklearn의 iris 데이터셋에서 1.0 정확도가 나오는 건 사실상 과적합일 가능성이 큼.
그래서 위의 향후 개선&확장 방향을 적용해도 결과 정확도 자체는 크게 달라지지 않을 듯 함.
< 추가 학습 >
# 1. 라이브러리 불러오기
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score, learning_curve
from sklearn.linear_model import LogisticRegression
from sklearn.dummy import DummyClassifier
from sklearn.utils import resample
import numpy as np
# 2. 데이터 로드 및 분할
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42
)
# 3. 교차검증 (Cross‑Validation)
# - 5‑Fold CV로 학습 데이터에서 모델 안정성 평가
'''
- 단일 테스트 셋 점수만 보면 과적합인지 모름
- CV는 여러 번 평가해 평균 분산을 보므로, 모델 안정성을 객관적으로 판단할 수 있음
'''
clf = LogisticRegression(max_iter=200)
cv_scores = cross_val_score(clf, X_train, y_train, cv=5)
print("1) 교차검증 CV 점수:", cv_scores)
# 1) 교차검증 CV 점수: [1. 1. 0.86363636 1. 0.95454545]
# 5번 분할 중 세 번은 100%, 한 번은 85%, 한 번은 95%로 나옴 => 단일 분할 보다 평가가 불안정 할 수 있음을 보여줌
# 4. 러닝 커브 (Learning Curve)
# - 학습 곡선을 통해 데이터 규모 증가에 따른 오버/언더피팅 파악
# 데이터를 더 모으면 성능이 오를까? 지금 과적합인가?를 시각적으로 증명해보기 위함
train_sizes, train_scores, test_scores = learning_curve(
clf, X_train, y_train, cv=5,
train_sizes=np.linspace(0.2, 1.0, 5)
)
print("\n2) 러닝 커브 학습 크기:", train_sizes)
print(" 러닝 커브 평균 학습 점수:", np.mean(train_scores, axis=1))
print(" 러닝 커브 평균 검증 점수:", np.mean(test_scores, axis=1))
'''
2) 러닝 커브 학습 크기: [17 35 53 71 89]
러닝 커브 평균 학습 점수: [1. 0.96571429 0.9509434 0.95774648 0.96629213]
러닝 커브 평균 검증 점수: [0.93675889 0.91067194 0.93715415 0.94624506 0.96363636]
'''
# 학습 정확도는 항상 95~100%로 매우 높고, 검증과 차이가 적어 과적합도 크지 않음.
# 5. 간단한 정규화·정칙화 비교 (Regularization Comparison)
# - 기본 C=1.0 vs C=0.1 비교
# 과적합이 의심될 때 모델을 더 단순하게 해서 일반화 성능을 확인해보고자 함.
clf_default = LogisticRegression(max_iter=200)
clf_reg = LogisticRegression(C=0.1, max_iter=200)
scores_default = cross_val_score(clf_default, X_train, y_train, cv=5)
scores_reg = cross_val_score(clf_reg, X_train, y_train, cv=5)
print("\n3) 기본 LR CV 점수:", scores_default)
print(" 정칙화 LR(C=0.1) CV 점수:", scores_reg)
'''
3) 기본 LR CV 점수: [1. 1. 0.86363636 1. 0.95454545]
정칙화 LR(C=0.1) CV 점수: [1. 0.95652174 0.81818182 0.95454545 0.90909091]
'''
# C=0.1(강한 정칙화)은 일부 Fold에서 정확도가 떨어졌지만, 모델 복잡도를 낮춰 과적합 위험을 완화
# 6. 단순 모델 대비 Baseline (Dummy Classifier)
# - 가장 빈도가 높은 클래스만 예측하는 더미 모델과 비교
# “우리 모델이 진짜 학습했는가?”를 확인하려면, 무작위·단순 전략보다 반드시 높은 성능을 보여야 하기 때문
dummy = DummyClassifier(strategy="most_frequent")
dummy_scores = cross_val_score(dummy, X_train, y_train, cv=5)
print("\n4) DummyClassifier CV 점수:", dummy_scores)
# 4) DummyClassifier CV 점수: [0.34782609 0.34782609 0.31818182 0.36363636 0.36363636]
# 학습 데이터에서 가장 많은 클래스(‘setosa’ 등)만 예측했을 때 약 34%의 정확도가 나옴
# 7. Bootstrap Resampling (OOB 평가)
# - 부트스트랩 샘플링 후 OOB(Out‑Of‑Bag) 점수 평균 계산
# 데이터 샘플링 변동성에 따른 성능 편차를 확인하고, 모델이 특정 샘플에 과도하게 의존하지 않는지 검증하기 위해
n_bootstraps = 50
n_samples = len(X_train)
boot_scores = []
for i in range(n_bootstraps):
# 부트스트랩 샘플 인덱스와 OOB 인덱스 생성
indices = resample(np.arange(n_samples), replace=True, random_state=i)
oob_indices = np.setdiff1d(np.arange(n_samples), indices)
if len(oob_indices) == 0:
continue
X_bs, y_bs = X_train[indices], y_train[indices]
X_oob, y_oob = X_train[oob_indices], y_train[oob_indices]
clf.fit(X_bs, y_bs)
score = clf.score(X_oob, y_oob)
boot_scores.append(score)
print("\n5) Bootstrap OOB 점수 예시 (상위 5개):", boot_scores[:5])
print(" Bootstrap 평균 OOB 점수:", np.mean(boot_scores))
'''
5) Bootstrap OOB 점수 예시 (상위 5개): [0.8636363636363636, 0.9142857142857143, 0.975, 0.9285714285714286, 0.9782608695652174]
Bootstrap 평균 OOB 점수: 0.9540436934616691
'''
+ ) 모델 성능은 높고 의미 있다. : 교차검증, Bootstrap 모두 95% 이상의 안정적인 결과
+ ) 약간의 과적합 소지 있음 : 정칙화나 더 엄격한 검증 기법을 도입해 과적합을 다듬으면 더욱 견고해질 수 있음
+ ) 데이터를 늘리면 더 좋아진다. : 러닝커브 추세가 우상향 중. 추가 데이터 확보가 최우선 개선 과제
'Data Analysis Study' 카테고리의 다른 글
| 딥러닝 알고리즘 (Deep Learning Algorithms) 총정리 (0) | 2025.07.21 |
|---|---|
| 데이터 분석 심화 학습: Boosting 기법 (AdaBoost, Gradient Boosting, 의사결정 나무) (5) | 2025.07.21 |
| 앙상블(Ensemble) 기법 개념 및 종류 정리 (0) | 2025.07.20 |
| 최적화 함수 (Optimizer)의 차이 시각적 이해 (0) | 2025.07.20 |
| 딥러닝 다중 클래스 분류(Multi‑class Classification), 레이블 원-핫 인코딩, Softmax 출력, Categorical Cross‑Entropy 손실 함수 (3) | 2025.07.20 |