본문 바로가기
내가 하는 데이터분석/내가 하는 머신러닝

[앙상블, Ensemble] - Bagging with Python

by Pymoon 2023. 2. 9.

단일 결정트리의 단점을 극복하기 위해 여러 머신러닝 모델을 연결하여 더 강력한 모델을 방법인 앙상블(Ensemble)에 대해서 알아보자.

 

 

 

이 전의 머신러닝에서 우리는 K-최근접 이웃(K-Nearest Neighbor, KNN)에 대해서 다뤄보며 분류 알고리즘 뿐 아니라 회귀 알고리즘에 대해서도 알아보았다.

 

K-최근접 이웃(K-Nearest Neighbor, KNN) with Python

유사한 특성을 가진 데이터는 유사한 범주에 속하는 경향이 있다는 가정으로 데이터를 분류하는 K-최근접 이웃(KNN)에 대해서 정리해 보자. 이 전의 머신러닝에서는 초평면과 마진의 개념으로 분

py-moon.tistory.com

 

 

 

앙상블 기법에는 기본적으로 배깅(Bagging, Bootstrap Aggregating), 부스팅(Boosting), 랜덤포레스트(RandomForest)가 있다.

 

 

오늘은 주어진 자료에서 여러 개의 붓스트랩 자료를 생성하고 각각의 붓스트랩 자료에 예측모형을 만든 후 결합하여 최종 예측모형을 만드는 배깅(Bagging, Bootstrap Aggregating)에 대해서 알아보자.

 

 

그렇다면, 붓스트랩(Bootstrap)이란?

랜덤 샘플링의 일종으로, 중복을 허용하는 단순임의복원추출법을 적용하여 여러 개의 동일한 크기의 표본 자료를 획득하는 방법이다.

 

 

위 붓스트랩을 활용하여 머신러닝 알고리즘의 안정성과 정확도를 향상시키기 위해 고안된 일종의 앙상블 학습법의 알고리즘인 배깅은 분산을 줄이고 정확도를 개선하여 모델의 안정성을 크게 높여 과적합을 방지한다.

 

 

배깅을 이용한 머신러닝은 붓스트래핑(Bootstrapping) - 모델링(Modeling) - 보팅(Voting)의 순서를 가진다.

 

 

이제, 데이터를 가지고 직접 배깅을 실습해 보자.

 

 

 


첫 번째로 진행할 배깅을 이용한 분류 알고리즘은 캐글에서 지원하는 유방암 진단 데이터셋을 활용한다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings(action='ignore')
 
 
breast = pd.read_csv('data/breast-cancer.csv')
cs

 

> 배깅을 이용한 분류 알고리즘을 위한 라이브러리와 데이터를 미리 불러와준다.

 

 

 

breast.head()

> breast.head()를 통해서 데이터의 전반적인 모습을 확인할 수 있다.

 

 

 

sns.countplot(x = 'diagnosis', data = breast)

> 종속변수인 diagonosis 변수에 대해서 분포를 확인하고자 시각화해보았다.

 

> M은 약성을 의미하며 전체 데이터의 약 37%를 차지하고, B는 양성을 의미하며 전체 데이터의 약 63%를 차지하고 있다.

 

 

 

sns.relplot(x = 'area_mean', y = 'texture_mean', hue = 'diagnosis', data = breast)

> 분석을 위해서 독립변수를 area_mean, texture_mean변수로 한정하고, 독립변수와 종속변수 사이의 관계를 살펴보기 위해 산점도를 띠워본다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.model_selection import train_test_split
 
breast['diagnosis'= np.where(breast['diagnosis'== 'M'10)
 
= breast[['area_mean''area_worst']]
= breast['diagnosis']
 
train_x, test_x, train_y, test_y = train_test_split(x, y, stratify = y, test_size = 0.3, random_state = 42)
print(train_x.shape, test_x.shape, train_y.shape, test_y.shape)
 
 
(3982) (1712) (398,) (171,)
cs

 

> 앞서 정리하였듯이, 독립변수는 area_mean변수와 texture_mean변수이고 종속변수는 diagnosis변수로 지정해 준다.

 

> 그런 다음 데이터셋을 훈련 데이터와 테스트 데이터를 각각 7 : 3의 비율로 분할해 준다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
 
clf = BaggingClassifier(base_estimator = DecisionTreeClassifier())
pred = clf.fit(train_x, train_y).predict(test_x)
 
print('Accuracy Score : {:.2f}'.format(clf.score(test_x, test_y)))
 
 
Accuracy Score : 0.91
cs

 

> 모델 객체를 불러와서 배깅에서 수행할 분류기로 의사결정나무를 활용한다.

 

> 위에서 분할한 데이터를 활용해서 모델학습에 사용한 후 정확도를 반환해 본다.

 

 

 

pd.DataFrame(confusion_matrix(test_y, pred), index = ['True[0]', 'True[1]'], columns = ['Pred[0]', 'Pred[1]'])

> 학습된 모델에 대해서 혼동행렬과 함께 예측모형의 결과를 보다 자세하게 확인해 보자.

 

> 오분류된 경우가 적은 모습을 확인할 수 있다.

 

 

 

 

plot_roc_curve(clf, test_x, test_y)

> 분류 모델에서 성능지표로 활용하는 ROC곡선과 AUC값을 계산하여 분류 예측 결과를 시각화해본다.

 

> 이전에도 ROC곡선에 대해서 다룬 적이 있지만 그래프의 곡선이 뚜렷할수록 성능이 좋다는 결과를 가져온다.

 

> 위 결과에서 곡선모양과 AUC값을 확인해 보니 성능이 좋은 모델로 해석할 수 있다.

 

 

 

 

1
2
3
4
5
6
7
clf_oob = BaggingClassifier(base_estimator = DecisionTreeClassifier(), oob_score = True)
oob = clf_oob.fit(x, y).oob_score_
 
print(oob)
 
 
0.9209138840070299
cs

 

> 여기서 oob란, Out of Beg으로 배깅에서 붓스트래핑을 수행하면 평균적으로 각 예측기에 훈련데이터의 약 63% 정도만 샘플링이 된다.

 

> 따라서, 선택되지 않은 약 37%의 데이터로 모델의 성능을 평가하는 방법이 oob_score이다.

 

> 그 값을 확인해 보면 샘플링된 데이터로 훈련한 모델과 마찬가지로 좋은 성능이라는 것을 확인할 수 있다.

 

> 그리고, oob_score를 사용할 경우에 검증세트난 교차검증을 따로 수행하지 않아도 된다는 장점이 있다.

 

 

 


첫 번째로 진행할 배깅을 이용한 회귀 알고리즘은 캐글에서 지원하는 자동차 데이터셋을 활용해서 자동차의 가격을 예측해 보자.

 

 

 

 

1
2
3
4
5
6
7
8
9
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings(action='ignore')
 
 
car = pd.read_csv('data/CarPrice_Assignment.csv')
cs

 

> 회귀 실습에 사용될 라이브러리와 데이터셋을 불러와준다.

 

 

 

car.head()

> head()를 활용해서 데이터를 대략적으로 확인해 본다.

 

> 이번 데이터셋에서는 범주형 변수와 연속형 변수가 공존한다. 우리는 이번 분석에서 연속형 변수를 독립변수로, price 변수를 종속변수로 활용한다.

 

 

 

 

1
2
3
4
5
6
7
8
9
car_num = car.select_dtypes(['number'])
features = list(car_num.columns.difference(['car_ID''symboling''price']))
= car_num[features]
= car_num['price']
 
print(x.shape, y.shape)
 
 
(20513) (205,)
cs

 

> car.select_dtypes()를 활용해서 연속형 변수만을 추출한다.

 

> 모델 학습에 사용하도록 독립변수와 종속변수를 구별해 준다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor
 
reg = BaggingRegressor(base_estimator = DecisionTreeRegressor(), oob_score = True)
reg = reg.fit(x, y).oob_score_
 
print(reg)
 
 
0.9082976965563935
cs

 

> 분류 실습 때와 마찬가지로 모델 객체를 불러와서 배깅으로 사용할 분류기로 의사결정나무를 활용한다.

 

> 모델을 학습한 후에 oob_score를 확인해 본다.

 

 

 


 

OUTTRO.

 

 

오늘은 앙상블 기법 중 기본에 해당하는 배깅을 활용해서 분류와 회귀를 실습해 보았다.

 

 

한 가지 깨달은 점이 있다면, 붓스트랩으로 인해 선택받지 못한 데이터에 대해서도 성능을 평가할 수 있는 oob_score에 대해서 알아간다는 점이다.

 

oob가 교차검증의 역할을 하고 있기 때문에 분석하면서 거쳐야 할 검증과정을 따로 수행하지 않아도 된다는 장점이 메리트가 있어 보인다.