앙상블
여러 개의 예측모형들을 만든 후 예측모형들을 조합하여 하나의 최종 예측모형을 만드는 방법으로 다중 모델 조합, 분류기 조합이 있다.
앙상블 기법
- 배깅(Bagging)
- 주어진 자료에서 여러 개의
붓스트랩(bootstrap)
을 생성하고 각 붓스트랩 자료에 예측모형을 만든 후 결합하여 최종 예측모형을 만드는 방법이다. - 붓스트랩은 주어진 자료에서 동일한 크기의 표본을
랜덤 복원추출
로 뽑은 자료를 의미한다. - 최적의 의사결정나무를 구축할 때 가장 어려운 부분이 가지치기(pruning)이지만 배깅에서는 가지치기를 하지 않고 최대로 성장한 의사결정나무들을 활용한다.
- 훈련자료의 모집단의 분포를 모르기 때문에 실제 문제에서는 평균예측모형을 구할 수 없다. 이러한 문제를 해결하기 위해 훈련자료를 모집단으로 생각하고 평균예측모형을 구하여 분산을 줄이고 예측력을 향상시킬 수 있다.
- 주어진 자료에서 여러 개의
- 부스팅(Boosting)
- 예측력이 약한 모형들을 결합하여 강한 예측모형을 만드는 방법이다.
- 부스트 방법 중
Adaboost
는 이진분류 문제에서 랜덤 분류기보다 조금 더 좋은 분류기 n개에 각각 가중치를 설정하고 n개의 분류기를 결합하여 최종 분류기를 만드는 방법을 제안하였다. (가중치의 합은 1) - 훈련오차를 빠르고 쉽게 줄일 수 있다.
- Adaboost의 성능이 배깅보다 뛰어난 경우가 많다.
- 랜덤포레스트(Random Forest)
- 의사결정나무의 특징인 분산이 크다는 점을 고려하여 배깅과 부스팅보다 더 많은
무작위성
을 주어 약한 학습기들을 생성한 후 이를 선형 결합하여 최종 학습기를 만드는 방법이다. - 배깅 방식이 사용되며 배깅은 같은 알고리즘으로 여러 개의 분류기를 만들어
보팅(Voting)
으로 최종 결정하는 알고리즘이다 - 변수 제거 없이 실행되므로 정확도 측면에서 좋은 성과를 보인다.
- 최종 결과에 대한 해석이 어렵다는 단점이 있으나 예측력이 매우 높은 것으로 알려져있다.
- 의사결정나무의 특징인 분산이 크다는 점을 고려하여 배깅과 부스팅보다 더 많은
Library Import
1
2
3
4
5
6
7
8
9
10
11
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use('ggplot')
%matplotlib inline
# pip install graphviz
import graphviz
import warnings
warnings.filterwarnings('ignore')
1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.datasets import load_breast_cancer, load_boston, load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
from sklearn.ensemble import BaggingClassifier, BaggingRegressor
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.ensemble import AdaBoostClassifier, AdaBoostRegressor
from sklearn.ensemble import GradientBoostingClassifier, GradientBoostingRegressor
from sklearn.ensemble import VotingClassifier, VotingRegressor
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.metrics import accuracy_score, mean_squared_error, confusion_matrix, classification_report
Bagging
1
2
3
4
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target
1
2
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
1
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, stratify=y, random_state=42)
1
2
3
4
5
6
7
8
model = DecisionTreeClassifier(random_state=42)
bagging = BaggingClassifier(model)
bagging.fit(X_train, y_train)
y_pred = bagging.predict(X_test)
print("베깅 모델 학습 데이터 점수 : {}".format(bagging.score(X_train, y_train)))
print("배깅 모델 평가 데이터 점수 : {}".format(bagging.score(X_test, y_test)))
1
2
베깅 모델 학습 데이터 점수 : 1.0
배깅 모델 평가 데이터 점수 : 0.9333333333333333
1
print(classification_report(y_test, y_pred))
1
2
3
4
5
6
7
8
9
precision recall f1-score support
0 1.00 1.00 1.00 10
1 0.90 0.90 0.90 10
2 0.90 0.90 0.90 10
accuracy 0.93 30
macro avg 0.93 0.93 0.93 30
weighted avg 0.93 0.93 0.93 30
Voting
1
2
3
4
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = cancer.target
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 로지스틱 모델과 트리 모델 생성
model1 = LogisticRegression(random_state=42)
model2 = DecisionTreeClassifier(random_state=42)
# 위 두 모델을 결합하여 보팅 모델 생성
vo_clf = VotingClassifier(estimators=[('LR', model1), ('KNN',model2)], voting='soft')
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 보팅모델의 스코어 파악
vo_clf.fit(X_train, y_train)
pred = vo_clf.predict(X_test)
print('Voting accuracy : {0:.4f}'.format(accuracy_score(y_test, pred)))
print(confusion_matrix(y_test, pred))
print(classification_report(y_test, pred))
classifier = [model1, model2]
# 비교를 위해 각 모델 별 스코어 출력
for classifier in classifier :
classifier.fit(X_train, y_train)
pred = classifier.predict(X_test)
class_name = classifier.__class__.__name__
print('{0} accurcy : {1:.4f}'.format(class_name, accuracy_score(y_test, pred)))
print(confusion_matrix(y_test, pred))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Voting accuracy : 0.9474
[[40 3]
[ 3 68]]
precision recall f1-score support
0 0.93 0.93 0.93 43
1 0.96 0.96 0.96 71
accuracy 0.95 114
macro avg 0.94 0.94 0.94 114
weighted avg 0.95 0.95 0.95 114
LogisticRegression accurcy : 0.9649
[[40 3]
[ 1 70]]
DecisionTreeClassifier accurcy : 0.9474
[[40 3]
[ 3 68]]
Boosting
1. Gradient Boosting
부스팅 알고리즘은 여러개의 약한 학습기를 순차적으로 학습 - 예측하면서 잘못 예측한 데이터에 가중치를 부여해 오류를 개선해 나가면서 학습하는 방식이다. 그 중에서 GBM은 가중치 업데이트를 경사 하강법
을 이용한다. 정의된 손실 함수를 기준으로 오차를 계산하고 트리 기반의 약한 학습기를 만들어 오차를 줄일 수 있도록 가중치를 갱신하여 학습을 진행한다.
1
2
X = pd.DataFrame(load_breast_cancer().data, columns = load_breast_cancer().feature_names)
y = load_breast_cancer().target
1
2
scaler = StandardScaler()
scaled_X = scaler.fit_transform(X)
1
X_train, X_test, y_train, y_test = train_test_split(scaled_X, y, test_size=0.2, random_state=42)
1
2
3
gbc = GradientBoostingClassifier(random_state=42)
gbc.fit(X_train, y_train)
pred = gbc.predict(X_test)
1
print(classification_report(y_test, pred))
1
2
3
4
5
6
7
8
precision recall f1-score support
0 0.95 0.93 0.94 43
1 0.96 0.97 0.97 71
accuracy 0.96 114
macro avg 0.96 0.95 0.95 114
weighted avg 0.96 0.96 0.96 114
1
2
3
plt.figure(figsize = (10, 6))
sns.barplot(y=X.columns.tolist(), x=gbc.feature_importances_, edgecolor=(0, 0, 0))
plt.show()
2. Adaboost
1
2
3
4
5
6
7
8
model = AdaBoostRegressor(random_state=42)
model.fit(X_train, y_train)
predict = model.predict(X_test)
print("학습 데이터 점수 : {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수 : {}".format(model.score(X_test, y_test)))
print("MSE : {}".format(mean_squared_error(y_test, predict)))
1
2
3
학습 데이터 점수 : 0.9896234135602474
평가 데이터 점수 : 0.8864926623728349
MSE : 0.026664966280065792
3. XGBoost
early_stopping_rounds=100
은 평가 지표가 어느 지점에서 100번째까지 향상되지 않는다면 조기 종료하겠다는 옵션이다. 너무 급격하게 줄이면 성능향상의 여지가 있는데 조기종료되어 모델의 성능이 저하될 수 있으므로 적절한 수를 선택해야 한다.eval_metric='logloss'
는 평가지표로 logloss를 사용하겠다는 옵션이다.eval_set=[(X_test, y_test)]
는 평가를 할 데이터셋을 명시한다.verbose
는 각 과정을 보여주느냐 마느냐를 결정하는 옵션이다. 기본값은 0으로 각 과정을 보여주지 않는것으로 되어있다.
1
2
3
4
5
6
7
model = XGBClassifier(random_state=42, eval_metric='logloss')
model.fit(X_train, y_train)
predict = model.predict(X_test)
print("학습 데이터 점수 : {}".format(model.score(X_train, y_train)))
print("평가 데이터 점수 : {}".format(model.score(X_test, y_test)))
1
2
학습 데이터 점수 : 1.0
평가 데이터 점수 : 0.956140350877193
1
2
3
4
5
6
# xgboost 안의 plot_importance를 활용해서 변수의 중요도를 시각화
from xgboost import plot_importance
fig, ax = plt.subplots(figsize=(10, 12))
plot_importance(model, ax=ax)
plt.show()