반응형

1. Stacking 앙상블 개요
Stacking(스태킹) 은 여러 개의 서로 다른 모델이 만든 예측 결과 자체를 새로운 피처로 사용하여
또 다른 모델(메타 모델, Meta Model)이 최종 예측을 수행하는 앙상블 기법입니다.
즉,
- 1단계(Base Model) : 여러 개의 서로 다른 모델이 예측 수행
- 2단계(Meta Model) : 각 모델의 예측 결과를 입력값으로 다시 학습
하는 구조를 가집니다.
“모델들의 판단 결과를 다시 하나의 모델에게 맡기는 방식”이라고 이해하면 됩니다.
2. Basic Stacking Model 구조
⚠️ 주의점
Basic Stacking은 테스트 데이터를 메타 모델 학습에 재사용하기 때문에
데이터 누수(Data Leakage) 와 오버피팅 위험이 있습니다.
→ 개념 이해용으로는 적절하지만, 실무에서는 개선된 방식이 필요합니다.
3. 데이터 및 라이브러리 로드
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
4. 데이터 로딩 및 분리
cancer_data = load_breast_cancer()
X_data = cancer_data.data
y_label = cancer_data.target
X_train, X_test, y_train, y_test = train_test_split(
X_data,
y_label,
test_size=0.2,
random_state=0
)
- 유방암 데이터셋
- 이진 분류 문제
- 학습 80%, 테스트 20%
5. 개별 기반 모델(Base Model) 및 메타 모델 생성
# 개별 기반 모델
knn_clf = KNeighborsClassifier(n_neighbors=4)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0)
dt_clf = DecisionTreeClassifier()
ada_clf = AdaBoostClassifier(n_estimators=100)
# 메타 모델
lr_final = LogisticRegression(C=10)
구성 의도
- KNN : 거리 기반
- Decision Tree : 규칙 기반
- RandomForest : 배깅 기반 앙상블
- AdaBoost : 부스팅 기반 앙상블
→ 서로 다른 학습 방식의 모델을 섞어 다양성(Diversity) 확보
6. 개별 모델 학습
knn_clf.fit(X_train, y_train)
rf_clf.fit(X_train, y_train)
dt_clf.fit(X_train, y_train)
ada_clf.fit(X_train, y_train)
7. 개별 모델 예측 및 성능 확인
knn_pred = knn_clf.predict(X_test)
rf_pred = rf_clf.predict(X_test)
dt_pred = dt_clf.predict(X_test)
ada_pred = ada_clf.predict(X_test)
print(f'스태킹전 knn 정확도 : {round(accuracy_score(y_test, knn_pred), 2)}')
print(f'스태킹전 rf 정확도 : {round(accuracy_score(y_test, rf_pred), 2)}')
print(f'스태킹전 dt 정확도 : {round(accuracy_score(y_test, dt_pred), 2)}')
print(f'스태킹전 ada 정확도 : {round(accuracy_score(y_test, ada_pred), 2)}')
knn : 0.92
rf : 0.96
dt : 0.91
ada : 0.97
- AdaBoost, RandomForest가 상대적으로 우수
- 하지만 각 모델의 오답 패턴은 서로 다름
8. 예측 결과를 Stacking 형태로 변환
pred = np.array([knn_pred, rf_pred, dt_pred, ada_pred])
print(pred.shape)
(4, 114)
pred = np.transpose(pred)
print(pred.shape)
(114, 4)
👉 이제 각 행은
[KNN 예측, RF 예측, DT 예측, Ada 예측] 이라는 새로운 피처 벡터가 됩니다.
9. 메타 모델 학습 및 예측 (⚠️ 오버피팅 구조)
lr_final.fit(pred, y_test)
final = lr_final.predict(pred)
print(f'스태킹 후 meta 정확도 : {round(accuracy_score(y_test, final), 2)}')
스태킹 후 meta 정확도 : 0.97
문제점 설명
- 테스트 데이터를 다시 학습에 사용
- 실제 일반화 성능을 보장하지 못함
- 실무에서는 사용하면 안 되는 방식
👉 이를 해결하기 위해 교차검증 기반 Stacking이 필요합니다.
10. CV(교차검증) 기반 Stacking
핵심 아이디어
- 훈련 데이터 내부에서 교차검증을 통해 메타 모델용 학습 데이터 생성
- 테스트 데이터는 한 번도 학습에 사용되지 않음
11. Stacking 데이터 생성 함수 정의
from sklearn.model_selection import KFold
def get_stacking_base_datasets(model, X_train_n, y_train_n, X_test_n, n_folds):
kf = KFold(
n_splits=n_folds,
shuffle=True,
random_state=0
)
# 메타 모델 학습용 데이터
train_fold_pred = np.zeros((X_train_n.shape[0], 1))
# 테스트 데이터 예측값 저장
test_pred = np.zeros((X_test_n.shape[0], n_folds))
print(model.__class__.__name__, "model 시작")
for folder_counter, (train_index, valid_index) in enumerate(kf.split(X_train_n)):
print('폴드세트 시작')
X_tr = X_train_n[train_index]
y_tr = y_train_n[train_index]
X_te = X_train_n[valid_index]
model.fit(X_tr, y_tr)
# 검증 데이터 예측 → 메타 학습 데이터
train_fold_pred[valid_index, :] = model.predict(X_te).reshape(-1, 1)
# 테스트 데이터 예측 → 폴드별 저장
test_pred[:, folder_counter] = model.predict(X_test_n)
# 테스트 예측값 평균
test_pred_mean = np.mean(test_pred, axis=1).reshape(-1, 1)
return train_fold_pred, test_pred_mean
12. 각 모델별 Stacking 데이터 생성
knn_train, knn_test = get_stacking_base_datasets(knn_clf, X_train, y_train, X_test, 7)
rf_train, rf_test = get_stacking_base_datasets(rf_clf, X_train, y_train, X_test, 7)
dt_train, dt_test = get_stacking_base_datasets(dt_clf, X_train, y_train, X_test, 7)
ada_train, ada_test = get_stacking_base_datasets(ada_clf, X_train, y_train, X_test, 7)
13. 최종 Stacking 학습/테스트 데이터 생성
Stack_final_X_train = np.concatenate(
(knn_train, rf_train, dt_train, ada_train),
axis=1
)
Stack_final_X_test = np.concatenate(
(knn_test, rf_test, dt_test, ada_test),
axis=1
)
print(f'원본 학습 피쳐데이터셋 {X_train.shape}')
print(f'원본 테스트 피쳐셋 {X_test.shape}')
print(f'스태킹 학습 피쳐데이터셋 : {Stack_final_X_train.shape}')
print(f'스태킹 테스트 피쳐 데이터셋 {Stack_final_X_test.shape}')
원본 학습 : (455, 30)
원본 테스트 : (114, 30)
스태킹 학습 : (455, 4)
스태킹 테스트 : (114, 4)
14. 메타 모델 최종 학습 및 평가
lr_final.fit(Stack_final_X_train, y_train)
stack_final = lr_final.predict(Stack_final_X_test)
print(f'최종 모델 예측 정확도 : {accuracy_score(y_test, stack_final)}')
15. 결론 정리
방식특징
| Basic Stacking | 개념 이해용, 오버피팅 위험 |
| CV 기반 Stacking | 실무 사용 가능 |
| 핵심 | 예측값을 다시 학습 데이터로 사용 |
| 중요 포인트 | 반드시 교차검증 사용 |
Stacking은 모델 성능을 끌어올리는 강력한 방법이지만,
데이터 누수를 방지하는 구조 설계가 필수입니다.
반응형
'Programming' 카테고리의 다른 글
| 내용 요약 정리 (Classification · Tree · Ensemble · Feature Engineering) (0) | 2026.01.02 |
|---|---|
| Feature Selection 실전 : 정리모델 성능과 해석력을 동시에 잡는 방법 (0) | 2026.01.01 |
| Credit Card Fraud Detection 3편 : 이상치 제거(IQR)와 SMOTE 오버샘플링을 통한 성능 개선 (0) | 2025.12.26 |
| Credit Card Fraud Detection 2편 : 데이터 분포도 변환 후 모델 학습·예측·평가 (0) | 2025.12.26 |
| Credit Card Fraud Detection 1편 : Feature Engineering과 Baseline 모델 성능 분석 (0) | 2025.12.26 |