Hands-On Machine Learning

[핸즈온머신러닝] CH7. 앙상블(Ensemble) 학습

에움길98 2022. 12. 9. 12:21

목차 

  1. 앙상블 기법이란?
  2. 앙상블 기법의 종류
    1. 보팅
    2. 배깅, 페이스팅
    3. 랜덤 포레스트
    4. 부스팅
    5. 스태킹

 


1. 앙상블 기법이란?

여러개의 학습 모델(분류, 회귀 ...) 을 학습하여 학습된 각 모델에서 예측을 만들어 낸 후

그 예측들을 결합하여 보다 정확도가 높은 예측을 만들어 내는 기법이다

 

이러한 앙상블기법에는 보팅 (하드, 소프트), 배깅, 페이스팅, 부스팅 등 다양한 기법들이 존재하고 있


2. 앙상블 기법의 종류


 2.1 Voting 보팅 (투표 기반 분류기)

 

보팅

 

보팅은 말 그대로 같은 데이터셋을 통해서 각 모델들을 학습시키고 이들의 예측을 투표를 통해서 최적의 예측으로 만들어 내는 방법으로 하드 보팅 소프트 보팅이 있다.

 

 

2.1.1 하드 보팅(Hard voting)과 소프트 보팅(Soft voting)

 

하드 보팅  Hard Voting : 각 모델 예측 결과를 단순 다수결로 결정하여 최적의 예측을 만드는 앙상블 기법
소프트 보팅 Soft Voting : 각 모델의 예측 확률을 평균하여 최적의 예측을 만드는 앙상블 기법

쉽게 설명하자면 하드 보팅은 단순 다수결로 결과를 결정하고 소프트 보팅은 각 모델의 확률을 평균하여 결과를 결정한다

  *일반적으로 소프트보팅이 하드 보팅보다 조금 더 높은 정확성을 내는 반면 학습 시간이 조금 더 걸린다

 

2.1.2 코드

import pandas as pd

from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier

#각 모델들 정의
lr_clf = LogisticRegression(solver='liblinear')
knn_clf = KNeighborsClassifier(n_neighbors=8)

#VotingClassifier정의 및 사용할 모델과 voting 방법 입력
v_clf = VotingClassifier(estimators = [('LR', lr_clf), ('KNN', knn_clf)], voting = 'soft')

#학습
v_clf.fit(X_train, y_train)

#예측
pred = v_clf.predict(X_test)

보팅은 sklearn의 VotingClassifier를 사용하면 되고 

하드보팅과 소프트보팅은 파라미터에 voting ='soft' or ' hard'로 설정해주면 된다

 


 2.2 배깅(Bagging)과 페이스팅(Pasting)

배깅

앞에서 살펴본 보팅은 똑같은 데이터셋을 활용하여 각 모델들을 학습시켰다. 

그러나 이는 모델의 과적합을 만들어 낼 가능성을 높인다

따라서 Bootstrap Aggregating의 약자인 배깅은 각 모델마다 다른 데이터 셋을 활용하여 학습을 하는데 

이때 훈련 데이터 셋에서 샘플링을 하여 각 데이터셋을 구성해준다 

여기서 각 샘플링에 중복을 허용하면 배깅 (복원추출이다)이고 각 샘플링에 중복을 허용하지 않으면 페이스팅이다

 

배깅은 '분류'일 때 통계적 최빈값(가장 많이 예측한 결과)을 활용하여 최종 결과를 만들어 내고 

'회귀'일 경우 평균을 계산하여 최종 결과를 만들어낸다

 

2.2.1 oob 평가

배깅을 활용하면 어떤 샘플은 한 모델에서 여러 번 사용될 수 있고 어떤 것은 전혀 선택되지 않을 수 있다

즉, 선택받지 못하는 훈련 데이터들이 존재하게 되는데 이를 oob (out-of-bag)샘플이라고 한다

 

이들을 활용하지 않는다면 오히려 데이터적으로 손해이다

또한 이들을 활용할 수 있다면 굳이 별도의 validation 데이터 셋을 구성할 필요가 없다 

따라서 배깅에서 평가할 때 oob 샘플을 활용하는 것이 좋다 

oob 평가는 각 모델의 평균으로 만들어 진다

 

2.2.2 코드

import pandas as pd

from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier



#BaggingClassifier정의 및 사용할 모델과 oob평가 설정
b_clf = BaggingClassifier(
	DecisionTreeClassifier(), n_estimators = 500, 
    	boostrap =True, n_jobs = -1, oob_score=True)

#학습
b_clf.fit(X_train, y_train)

#예측
pred = v_clf.predict(X_test)

배깅은 sklearn의 BaggingClassifier를 활용하면된다

여기서 중복 추출을 허용할 거면 boostrap = True로 하고 (배깅) 허용하지 않을 거면 False(페이스팅)로 하면된다

똫나 oob평가 활용 여부는 'oob_score' 파라미터로 설정하면 된다

 


 2.3 랜덤 포레스트(Random Forest)

배깅의 일종으로 사실 배깅안에 포함되는 모델

배깅과 랜덤 포레스트의 차이점은 ? : 랜덤 포레스트는 데이터 셋 뿐만 아니라 '설명 변수'도 무작위로 뽑아서 학습

 

높은 성능을 내는 모델로 많이 사용되고 있다

 

장점 :

랜덤 포레스트는 설명변수를 무작위로 추출하여 사용하기 때문에 각 모델의 상관관계를 줄 일 수 있다

즉, 모델의 과적합을 방지할 수 있음

또한 모델의 학습속도가 빠르고 높은 정확성을 낼 수 있다

 

단점 :

하지만 전형적인 '블랙박스'모델 이기 때문에 해석이 불가능함 즉, 결과의 도달 방법을 해석하기 매우 어려움

 

2.3.1  코드

import pandas as pd
from sklearn.ensemble import RandomForestClassifier

#모델정의
rfc = RandomForestClassifier(random_state=0)

#학습
rfc.fit(X_train, y_train)

#예측
y_pred = rfc.predict(X_test)

랜덤 포레스트는 sklearn의 RandomForestClassifier를 이용하면 된다

 

 


 

2.4 부스팅 (Boosting)

부스팅

여러 모델을 연결하여 강한 모델을 만드는 앙상블 기법을 말한다

즉, 앞의 모델을 뒤의 모델이 보완하면서 더 좋은 모델을 만들어 내는 것이다

 

이러한 부스팅에는 에이다 부스트 AdaBoost와 그레이디언트 부스팅 Gradient boosting이 있다

 

2.4.1 에이다 부스트 AdaBoost

에이다 부스트

에이다 부스트는 앞의 모델이 (이전모델) '과소적합' 했던 훈련 샘플의 가중치를 높여

학습해 나가는 앙상블 기법이다

 

예를들어 설명하면 모델을 만들 때 먼저 알고리즘이 기반이 되는 첫 번째 모델을 훈련세트로 훈련하고

예측을 만들어낸다. 그런 다음 알고리즘이 잘못 분류된 훈련 샘플의 가중치를 상대적으로 높여

두번째 모델에서 업데이트된 가중치를 사용하여 다시 예측을 만들어 내고

계속해서 이러한 가중치를 업데이트 하는 방식으로 진행된다

에이다 부스트 가중치 과정 코드 (구현) :
stackoverflow.com/questions/55318330/why-is-the-error-of-my-adaboost-implementation-not-going-down
*경사하강법과 비슷한 과정으로 진행
차이점 : 경사하강법은 모델의 파라미터를 수정해나가지만 부스팅은 모델을 추가해 나간다

*모든 훈련이 마치면 배깅이나 페이스팅과 같은 방식을 통해 예측을 만들어낸다. 
하지만, 이들은 연속된 학습 기법이기 때문에 모델 마다 다른 가중치를 적용한다

(연속된 학습 기법의 중요한 단점 = 각 예측기는 이전 예측가 학습 및 평과된 이후에 학습 될 수 있기 때문에 병렬화가 어렵다. 따라서 확장성이 높지 않다)

모델의 가중치를 수정해 나가는 과정

<수정 과정>

  1.  각 샘플 가중치 W**(i)는 초기에 1/m로 초기화
  2. 첫 번째 모델 학습이후, 가중치가 적용된 에러율 r이 훈련 세트에 대해 계산 (전체 가중치 총합에 대한 예측이 틀린 가중치 합의 비율) - (B)식
  3. 그런다음 모델에 대한 가중치를 계산 - (C)식  [모델이 정확할 수록 가중치가 더 높아짐, 무작위로 예측하는 정도(약50%이하) 가중치가 0에 가깝고 그것도 나쁘면 음수로]
  4. 그리고 에이다부스트 알고리즘식(D)를 통해서 샘플의 가중치를 업데이트, 잘못 분류된 샘플의 가중치가 증가
  5. 마지막으로 모든 샘플의 가중치를 정규화 
  6. 지정된 모델 수에 도달하거나 완벽한 모델이 만들어지면 중지하고, 각 모델의 예측과 각 모델의 가중치를 곱한다음 합하여 가중치 합이 가장 큰 클래스가 예측 결과가 된다

[코드]

from sklearn.ensemble import AdaBoostClassifier

ada_clf = AdaBoostClassifier(
	DecisionTreeClassifier(max_depth=1), n_estimators=200,
    algorithm="SAMME", learning_rate=0.5)
    
ada_clf.fit(X_train, y_train)

에이다 부스트도 sklearn에 구현되어 있다

여기서 algorithm의 매개변수에는 'SAMME.R'과 'SAMME'가 있는데 다중 클래스일 경우 활용하는 것으로 (개일 경우 SAMME와 기본 Adaboost 알고리즘은 같다.

 SAMME는 기본 Adaboost 알고리즘 2-(c)을 수정한 것으로  아래의 식을 사용한다. (클래스를 이용)

 

 

SAMME.R은 아래의 수식을 2-(c)로 이용하고 클래스가 아니라 클래스의 확률을 이용한다

 


2.4.2 그레이디언트 부스팅 Gradient Boosting

그래이디언트 부스팅, 줄여서 GBM으로 불리는 기법은 현재 머신러닝에서 가장좋은 성능을 내고 있는 기법

XGboost, LGBM, CatBoost등 머신러닝 대회에서 상위권을 차지하고 있는 대부분의 모델이 그레이디언트 부스팅 기법을 적용한 모델이다

 

그레이디언트 부스팅도 에이다부스트 처럼 이전 모델의 오차를 보정하도록 예측기를 순차적으로 추가한다

그러나 에이다부스트가 샘플의 가중치를 수정한다면 그레이디언트 부스팅은 이전 모델이 만든 잔여 오차에 새로운 모델을 학습시킨다

 

즉, 데이터 샘플링 없이 y값 즉, 목표값을 수정해서 이전모델이  예측하지 못한 예측을 예측하는 방법

 

 

Gradient Boosting from scratch

Simplifying a complex algorithm

blog.mlreview.com

 

 

단점 : 학습 데이터 셋에 과적합될 가능성이 높다

따라서 다양한 규제를 활용해 과적합을 피하는 것이 중요하다

 

[코드]

 

from sklearn.tree import DecisionTreeRregressor

tree_reg1 = DecisionTreeRregressor(max_depth=2)
tree_reg1.fit(X,y)

y2 = y - tree_reg1.predict(X)
tree_reg2 = DecisionTreeRregressor(max_depth=2)
tree_reg2.fit(X, y2)

....

y_pred = sum(tee.predict(X_new) for tree in (tree_reg1, tree_reg2 .....))

직접 구현한 그레디언트 부스팅 과정 

from sklearn.ensemble improt GradientBoostingRegressor

gbrt = GradientBoostingRegressor(max_depth = 2, n_estimators=3, learning_rate = 1.0)
gbrt.fit(X, y)


#subsample 하이퍼 파라미터 -> 확률적 그레이디언트 부스팅

그레이디언트 부스팅도 sklearn에 구현되어 있다 

여기서 subsample 하이퍼 파라미터를 추가해주면(0~1) 그 만큼 확률적 그레이디언트 부스팅을 할 수 있다

 

 

그레디언트 부스팅을 활용한 대표적 모델 (성능좋은)
1. XGBoost (extra gredient boost model)
https://wooono.tistory.com/97
2. LGBM(light gredient boost model)
https://nicola-ml.tistory.com/51
3. catboost
https://julie-tech.tistory.com/119

 


2.5 스태킹(Stacking)

앞에서 살펴본 모델들은 마지막 예측을 만들때 하드 보팅이나 소프트 보팅 같은 간단한 함수를 활용해서 예측을 만들었다

그러나 간단한 함수를 사용하는 대신에 모델을 활용해서 최종 예측을 하는 방법이 등장했는데 이걸 '스태킹'이라고 한다

 

캐글이나 데이콘 같은 대회에서 조금더 성능을 올리기 위해서 사용된다 (드라마틱한 변화는 없다)

 

방법은 간단하다

각 모델의 예측을 활용해서 새로운 X_train을 만든다

그리고 이렇게 만들어진 X_train을 통해서 y_train을 예측하는 것이다

 

[코드]

from sklearn.ensemble import StackingClassifier
from catboost import CatBoostClassifier
from lightgbm import LGBMClassifier
from xgboost import XGBClassifier 
from sklearn.ensemble import RandomForestClassifier



catc =  CatBoostClassifier(**cat_best_param)
lgbc =  LGBMClassifier(**lgb_best_param)
xgc = XGBClassifier(**xgboost_best_param)
rfc = RandomForestClassifier(**rf_best_param)

#메타모델 지정
model1 = [('cat', catc), ('lgb', lgbc), ('xgb', xgc), ('rfc', rfc)]
model2 = catc

stacking_model = StackingClassifier(estimators=model1, final_estimator=model2)
stacking_model.fit(X_train, y_train)

책에서는 스태킹이 sklearn에 없다고 하는데 추가되었다

여기서 각 모델을 지정해주고 모델의 파라미터를 설정해준다

그리고 이를 model1 과 model2로 묶는데 

model1은 각 모델의 예측을 뽑아내서 새로운 X_train을 만들어낸다 

그리고 난 후 modl2의 모델로 최종예측을 한다

(파라미터로 cv 교차검증을 하면 더 성능이 올라간다)

그리고 model1 같은 경우 3개 이상의 모델로 구성해줘야 어느 정도의 성능 개선을 볼 수 있다

 

단점 : 과적합의 위험이 높음