Machine Learning/Advanced (hands on machine learning)

19. 앙상블 학습과 랜덤 포레스트 - 투표 기반 분류기

jwjwvison 2021. 5. 22. 17:12

 일련의 예측기(즉, 분류나 회귀 모델)로부터 예측을 수집하면 가장 좋은 모델 하나보다 더 좋은 예측을 얻을 수 있다. 일련의 예측기를 앙상블이라고 부르기 때문에 이를 앙상블 학습(ensemble learning)이라고 하며, 앙상블 학습 알고리즘은 앙상블 방법이라고 한다.

 

 앙상블 항법의 예를 들면 훈련 세트로부터 무작위로 각기 다른 서브셋을 만들어 일련의 결정트리 분류기를 훈련시킬 수 있다. 예측을 하려면 모든 개별 트리의 예측을 구하면 된다. 그런 다음 가장 많은 선택을 받은 클래스를 예측으로 삼는다. 결정 트리의 앙상블을 랜덤 포레스트 라고 한다. 간단한 방법임에도 랜덤 포레스트는 오늘날 가장 강력한 머신러닝 알고리즘 중 하나이다.

 

 정확도가 80%인 분류기 여러 개를 훈련시켰다고 가정하자. 아마도 로지스틱 회귀 분류기, SVM 분류기, 랜덤 포레스트 분류기, K-최근접 이웃 분류기 등을 가지고 있을 수 있다.

 더 좋은 분류기를 만드는 매우 간단한 방법은 각 분류기의 예측을 모아서 가장 많이 선택된 클래스를 예측하는 것이다. 이렇게 다수결 투표로 정해지는 분류기를 직접 투표 분류기라고 한다.

 

 조금 놀랍게도 이 다수결 투표 분류기가 앙상블에 포함된 개별 분류기 중 가장 뛰어난 것보다도 정확도가 높을 경우가 많다. (큰수의 법칙)

 

 다음은 여러 분류기를 조합하여 사이킷런의 투표 기반 분류기(VotingClassifier)를 만들고 훈련시키는 코드이다.

from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split

log_clf=LogisticRegression()
rnd_clf=RandomForestClassifier()
svm_clf=SVC()

X,y=make_moons(n_samples=500, noise=0.30, random_state=42)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=42)

voting_clf=VotingClassifier(
    estimators=[('lr',log_clf),('rf',rnd_clf),('svc',svm_clf)],
    voting='hard')
voting_clf.fit(X_train,y_train)

 

 각 분류기의 테스트셋 정확도를 확인해보자.

from sklearn.metrics import accuracy_score
for clf in (log_clf,rnd_clf,svm_clf,voting_clf):
  clf.fit(X_train,y_train)
  y_pred=clf.predict(X_test)
  print(clf.__class__.__name__,accuracy_score(y_test,y_pred))

 예상대로 투표 기반 분류기가 다른 개별 분류기보다 성능이 조금 더 높다.

 

 모든 분류기가 클래스의 확률을 예측할 수 있으면(즉, predict_proba() 메서드가 있으면), 개별 분류기의 예측을 평균 내어 확률이 가장 높은 클래스를 예측할 수 있다. 이를 간접 투표(soft voting)라고 한다. 이 방식은 확률이 높은 투표에 비중을 더 두기 때문에 직접 투표 방식보다 성능이 높다. 이 방식을 사용하기 위해서는 voting='hard'를 voting='soft'로 바꾸고 모든 분류기가 클래스의 확률을 추정할 수 있으면 된다. SVC는 기본값에서는 클래스 확률을 제공하지 않으므로 probability 매개변수를 True로 지정해야 한다. (이렇게 하면 클래스 확률을 추정하기 위해 교차 검증을 사용하므로 훈련 속도가 느려지지만 SVC에서 predict_proba() 메서드를 사용할 수 있다. 앞의 코드를 간접 투표 방식을 사용하도록 변경하면 91.2%의 정확도를 얻을 것이다.