728x90
1.Basic Stacking Model - Diagram
기반 모델들이 예측한 값들을 Stacking 형태로 만들어서 메타 모델이 이를 학습하고 예측하는 모델
- 서로 다른 알고리즘을 지닌 개별 모델들이 결합하여 최적의 성능을 가져온다는 부분은 유사
- 개별 모델들이 각각 생성한 예측 값들을 기반으로 메타 모델이 이를 다시 학습하고 예측한다는 부분에서 다르다
- 반드시 개별 모델보다 성능이 좋다는 것이 보장되지 않음: 오히려 결합하는 방식에 따라 성능이 떨어질 수도 있음
Stacking에 필요한 두 가지 모델
- 개별적인 기반 모델
- 최종 메타 모델 -> 개별 기반 모델의 예측데이터를 학습데이터로 만들어 예측 수행 -> 현실에서 자주 적용 X
Basic Stacking Model - Example
- 개별 모델이 반환한 예측값들은 메타 모델이 학습할 수 있도록 Stacking 형태로 재생성
- 각 예측값들은 Column 형태로 쌓아야 하므로 np.array( ) 안에 Row 형태로 쌓은 뒤 transpose를 통해 변환
스태킹 단계
- 모델별로 각각 학습시킨 뒤 예측 수행
- 모델별로 도출된 예측값을 다시 합해서 새로운 데이터세트 만듦
- 스태킹된 데이터 세트에 대해서 최종 모델에 적용
- 최종 예측 수행
Code 실습 - Basic Stacking Model
- 데이터 로딩
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
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
)
- 개별 Classifier와 최종 Stacking 데이터를 학습할 메타 Classifier를 생성
# 개별 ML 모델을 위한 Classifier 생성.
knn_clf = KNeighborsClassifier(n_neighbors=4)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0)
dt_clf = DecisionTreeClassifier()
ada_clf = AdaBoostClassifier(n_estimators=100)
# 최종 Stacking 모델을 위한 Classifier생성.
lr_final = LogisticRegression()
- 개별 Classifier 학습 / 예측 / 평가
# 개별 모델들을 학습.
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)
# 학습된 개별 모델들이 각자 반환하는 예측 데이터 셋을 생성하고 개별 모델의 정확도 측정.
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("KNN 정확도: {0:.4f}".format(accuracy_score(y_test, knn_pred)))
print("랜덤 포레스트 정확도: {0:.4f}".format(accuracy_score(y_test, rf_pred)))
print("결정 트리 정확도: {0:.4f}".format(accuracy_score(y_test, dt_pred)))
print("에이다부스트 정확도: {0:.4f}".format(accuracy_score(y_test, ada_pred)))
# KNN 정확도: 0.9211
# 랜덤 포레스트 정확도: 0.9649
# 결정 트리 정확도: 0.9123
# 에이다부스트 정확도: 0.9561
- 개별 모델의 예측 결과를 메타 모델이 학습할 수 있도록 스태킹 형태로 재생성
- 각 예측값들은 Column 형태로 쌓아야 하므로 np.array([ , , , .. , ]) 안에 Row 형태로 쌓은 뒤 transpose를 통해 변환
pred = np.array([knn_pred, rf_pred, dt_pred, ada_pred])
print(pred.shape)
# transpose를 이용해 행과 열의 위치 교환. 컬럼 레벨로 각 알고리즘의 예측 결과를 피처로 만듦.
pred = np.transpose(pred)
print(pred.shape)
# (4, 114)
# (114, 4)
- 메타 모델 학습 / 예측 / 평가
- Basic Stacking Model의 경우 여기에서 Overfitting이 발생
- 학습을 Test_DataSet으로 fitting 하기 때문
LogisticRegression( ).fit(pred, y_test)
- X 자리에 2차원 Data가 들어가야 함: Label Data Set을 X 자리에 넣으면 안된다
- pred: X_test로 predict한 값들의 집합
LogisticRegression( ).predict(pred)
lr_final.fit(pred, y_test)
final = lr_final.predict(pred)
print("최종 메타 모델의 예측 정확도: {0:.4f}".format(accuracy_score(y_test, final)))
# 최종 메타 모델의 예측 정확도: 0.9737
2. Cross-Validation Stacking
Cross - Validation Stacking 은 이에 대한 개선을 위해 개별 모델들이 각각 교차 검증으로 메타 모델을 위한 학습용 스태킹 데이터 생성과 예측을 위한 테스트용 스태킹 데이터를 생성한 뒤 이를 기반으로 메타 모델이 학습과 예측을 수행함.
STEP 1
- 각 모델별로 Cross - Validation을 이용한 원본 학습(M X N) / 테스트 데이터(K X N)를 예측한 결과 값을 기반으로 메타 모델을 위한 학습용(M X 1) / 테스트용(N X 1) 데이터를 생성함
- 개별 모델의 개수 = Fold 수
- 원본 학습, 검증 데이터 세트 크기 = $M \times N$ -> 최종 메타 모델에서 학습 데이터로 사용하는 데이터 크기 = $M \times 1$
- 원본 테스트 데이터 세트 크기 = $K \times N$ -> 최종 메타 모델에서 테스트 데이터로 사용하는 데이터 크기 = $K \times 1$
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
# 개별 기반 모델에서 최종 메타 모델이 사용할 학습 및 테스트용 데이터를 생성하기 위한 함수.
def get_stacking_base_datasets(model, X_train_n, y_train_n, X_test_n, n_folds):
# 지정된 n_folds값으로 KFold 생성.
kf = KFold(n_splits=n_folds, shuffle=False)
# 추후에 메타 모델이 사용할 학습 데이터 반환을 위한 넘파이 배열 초기화
train_fold_pred = np.zeros((X_train_n.shape[0], 1)) # 2차원 Data
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("\t 폴드 세트: ", folder_counter, " 시작 ")
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)
# train_fold_pred는 최종 메타 모델이 사용하는 학습 데이터, test_pred_mean은 테스트 데이터
return train_fold_pred, test_pred_mean
STEP 2
- STEP 1에서 개별 모델들이 생성한 학습용 데이터를 모두 stacking 형태로 합쳐서
- 메타 모델이 학습할 최종 학습용 데이터 세트를 생성함 (M X (개별 모델의 개수))
- 마찬가지로 각 모델들이 생성한 테스트용 데이터를 모두 스태킹 형태로 합쳐서
- 메타 모델이 예측할 최종 테스트 데이터 세트를 생성 (M X (개별 모델의 개수))
메타 모델은 최종적으로 생성된 학습 데이터 세트(Stack_final_X_train)와 원본 학습 데이터의 레이블 데이터(y_train)를 기반으로 학습한 뒤
최종적으로 생성된 테스트 데이터 세트를 예측(Stack_final_X_test)하고, 원본 테스트 데이터의 레이블 데이터(y_test, pred)를 기반으로 평가
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)
KNeighborsClassifier model 시작
폴드 세트: 0 시작
폴드 세트: 1 시작
폴드 세트: 2 시작
폴드 세트: 3 시작
폴드 세트: 4 시작
폴드 세트: 5 시작
폴드 세트: 6 시작
RandomForestClassifier model 시작
폴드 세트: 0 시작
폴드 세트: 1 시작
폴드 세트: 2 시작
폴드 세트: 3 시작
폴드 세트: 4 시작
폴드 세트: 5 시작
폴드 세트: 6 시작
DecisionTreeClassifier model 시작
폴드 세트: 0 시작
폴드 세트: 1 시작
폴드 세트: 2 시작
폴드 세트: 3 시작
폴드 세트: 4 시작
폴드 세트: 5 시작
폴드 세트: 6 시작
AdaBoostClassifier model 시작
폴드 세트: 0 시작
폴드 세트: 1 시작
폴드 세트: 2 시작
폴드 세트: 3 시작
폴드 세트: 4 시작
폴드 세트: 5 시작
폴드 세트: 6 시작
- 메타 모델이 학습할 최종 학습 데이터 세트 / 예측할 최종 테스트 데이터 세트 생성
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("원본 학습 피처 데이터 Shape:", X_train.shape, "원본 테스트 피처 Shape:", X_test.shape)
print(
"스태킹 학습 피처 데이터 Shape:",
Stack_final_X_train.shape,
"스태킹 테스트 피처 데이터 Shape:",
Stack_final_X_test.shape,
)
원본 학습 피처 데이터 Shape: (455, 30) 원본 테스트 피처 Shape: (114, 30)
스태킹 학습 피처 데이터 Shape: (455, 4) 스태킹 테스트 피처 데이터 Shape: (114, 4)
- 최종 메타 모델의 성능 평가
lr_final.fit(Stack_final_X_train, y_train)
stack_final = lr_final.predict(Stack_final_X_test)
print("최종 메타 모델의 예측 정확도: {0:.4f}".format(accuracy_score(y_test, stack_final)))
# 최종 메타 모델의 예측 정확도: 0.9737
728x90