7장 앙상블 학습과 랜덤 포레스트

주요 내용

기본 설정

7.1 다수결 분류기 (246쪽 또는 원서 p.189)

앙상블 학습 아이디어

앙상블 학습은 여러 대의 예측기의 결과를 수집하여 종합한 후에 예측값을 정하는 학습법이며, 앙상블 학습 알고리즘을 앙상블 기법이라 부른다. 성능이 약한 학습기 여러 대를 앙상블 학습에 이용하면 (보다) 강력한 학습기를 생성할 수 있다. 전제 조건은 다음과 같다.

큰 수의 법칙

이에 대한 확률적 근거를 "51%의 확률로 앞면이 나오는 동전 1만 번 던지기"를 통해 설명할 수 있으며, 아래 코드가 모의실험을 실행한다.

아래 코드는 '1만 번 던지기'를 10번 실행할 때 앞면이 나올 확률이 모두 50% 이상의 값으로 수렴하는 사실을 보여준다.

위 모의실험은 51% 정확도의 분류기를 충분히 많이 사용하면 양성/음성 예측에 대한 정확도가 매우 높아질 수 있다는 것을 보여준다. 물론 동전 던지기처럼 사용된 분류기들 사이의 독립성이 완벽하게 보장된다는 전제조건하에서만 그렇다. 그렇지 않다면 예측기들 사이의 어떤 의존성으로 인해 성능이 보다 떨어질 수도 있다.

실제로 51%의 확률로 앞면이 나오는 동전을 1만 번 던졌을 때 앞면이 50% 이상 나올 학률은 97% 이상이며, 1천 번만 던져도 75% 정도로 앞면이 많이 나온다. 이를 51% 정확도의 분류기를 1만 번 또는 1천 번 실행해서 모은 예측값들 중에서 다수인 것을 선택하는 방식을 선택했을 때 각각 97% 이상과 75% 정도의 정확성을 갖는다는 것으로 이해할 수 있다.

언급된 확률은 수학적으로 이항분포를 이용하여 아래와 같이 간단하게 계산할 수 있다. ensemble_win_proba() 함수는 정확도 p의 예측기 n개를 실행해서 다수결 원칙을 따랐을 때의 승률, 즉 다수결의 의견이 옳았을 확률을 계산한다. 이를 위해 이항분포의 누적밀도함수인 binom.cdf()를 이용한다.

참고: binom.cdf(x, n, p) 함수는 이항분포를 따르는 어떤 행위를 n번 시행할 때 확률 p의 사건이 x번 이하 발생할 확률을 계산하는 누적분포함수이다. 아래 코드에서는 50% 이상일 확률을 계산해야 하기에 x 대신에 50%보다 아주 조금 작은 빈도수를 입력하여 얻은 확률을 1에서 뺀다.

51%의 확률로 앞면이 나오는 동전을 1천 번 던져서 절반 이상 앞면이 나올 확률은 74.7%이다.

횟수를 1만 번으로 늘리면 확률이 97.7% 이상으로 나온다. 즉 1만 번 던지기를 100번하면 2번 정도만 5천 번 이하로 앞면이 나올 것으로 기대한다.

정확도 80% 정도의 이진분류기 10대를 이용한 앙상블 학습기의 성능이 99.3%까지 오를 수 있다. 매우 놀라운 결과이며, 실전에서 최적으로 튜닝된 모델의 성능을 앙상블 학습을 통해 개선하는 시도를 많이 한다. 물론 다시 한 번 말하지만 사용된 예측기의 다양성과 상호 독립성이 전제된 경우에 그럴 수 있다는 말이다.

직접 투표 vs. 간접 투표

아래 코드는 여러 종류의 분류기를 앙상블로 묶어 훈련시키는 방법을 보여준다. 사용되는 훈련데이터는 moons 데이터셋이다.

VotingClassifier 모델은 여러 개의 분류기를 이용한 앙상블 학습 분류기를 지원한다. 사용되는 분류기는 아래 세 개이다.

직접 투표

voring='hard'는 분류기들의 다수 예측값을 예측값으로 사용한다는 의미이다. 이런 방식을 직접 투표(hard voting)라 한다.

앙상블 학습에 사용된 분류기 세 개에 비해 분류기의 정확도 성능이 보다 좋은 것을 아래 코드에서 확인할 수 있다.

간접 투표

주어진 샘플의 클래스 확률을 계산하는 분류기들을 앙상블 학습에 사용하고 voring='soft'로 지정하면 분류기들의 클래스 확률의 평균값을 이용한다. 이런 방식을 간접 투표(soft voting)라 한다.

참고: 클래스 확률은 predict_proba() 메서드가 계산한다.

간접 투표 방식이 직접 투표 방식보다 정확도를 보다 높인다. 하지만 기본값은 하지만 voting=hard, 즉 직접 투표이다.

7.2 배깅과 페이스팅 (249쪽 또는 원서 p.192)

7.2.1 사이킷런의 배깅과 페이스팅 (250쪽 또는 원서 p.194)

그림 7-5 코드

아래 코드는 결정트리 모델 하나를 규제없이 사용할 때와 결정트리 500개를 사용하는 배깅 분류기의 성능을 비교하는 그래프를 그린다.

7.2.2 oob 평가 (252쪽 또는 원서 p.195)

아래 코드는 훈련 후 oob 평가를 진행한 결과를 보여준다.

테스트 성능과 유사한 결과이다.

oob_decision_function_ 속성은 훈련 샘플의 클래스 확률을 저장한다. 처음 10개 훈련 샘플의 클래스 확률은 다음과 같다.

7.4 랜덤 포레스트 (254쪽 또는 원서 p.197)

램덤포레스트는 기본적으로 결정트리를 이용한 배깅 모델을 최적화한 결과이다.

두 모델의 예측값의 97.6% 정도로 동일하다.

아래 코드는 배깅 기법이 작동하는 방식을 보여준다.

7.4.2 특성 중요도 (256쪽 또는 원서 p.198)

선택된 특성과 임곗값의 중요도를 훈련과정을 통해 측정한다.

붓꽃 특성 중요도

꽃잎의 길이와 너비가 가장 중요하다.

MNIST 이미지 특성 중요도

아래 코드는 MNIST 사진에 포함된 픽셀별 중요도를 이미지로 보여준다.

기본적으로 숫자가 쓰여진 사진 중심부의 큰 부분이 중요함을 아래 그림에서 확인할 수 있다.

7.5 부스팅 (257쪽 또는 원서 p.199)

7.5.1 에이다부스트 (258쪽 또는 원서 p.200)

그림 7-8 코드

사이킷런의 AdaBoostClassifier 모델 활용

AdaBoostClassifier의 기본 모델은 다음과 같다.

moons 데이터셋에 훈련시킨 결과는 다음과 같다.

7.5.2 그레이디언트 부스팅 (258쪽 또는 원서 p.203)

그레이디언트 부스팅 작동 과정

아래 코드는 잡음이 섞인 2차 함수 그래프 형태의 훈련 세트를 사용하여 그레이디언트 부스팅 기법을 회귀 모델 훈련에 적용하는 것을 보여준다.

먼저, 결정트리 모델을 훈련시킨다.

이어 잔여오차에 대해 다시 결정트리 모델을 훈련시킨다.

한번 더 잔여오차에 대해 다시 결정트리 모델을 훈련시킨다.

예측값은 사용된 예측기들의 예측값을 모두 더한 값이다.

아래 함수는 회귀모델의 예측 성능을 그래프로 그린다.

아래 코드는 앞서 훈련시킨 세 개의 모델의 예측 성능을 그래프로 그린다.

사이킷런의 GBRT 모델 활용

하이퍼파라미터가 다른 2 개의 GradientBoostingRegressor 모델의 성능 차이를 살펴본다.

아래 코드는 위 두 개의 다른 두 GBRT 모델의 성능을 그래프로 그린다.

조기종료를 사용하는 그레이디언트 부스팅

아래 코드는 120번 반복 훈련을 한 후에 최적의 예측기 개수를 알아내서 다시 훈련한 결과를 보여준다.

아래 코드는 평균제곱근오차가 5번 이상 개선되지 않을 때 훈련을 조기종료하도록 한다.

61개까지의 예측기를 사용하였다.

훈련중 얻은 평균제곱근오차의 최소값은 다음과 같다.

XGBoost

사이키런과 다른 패키지이며 추가로 설치해야 한다. (구글 코랩에서는 지원됨.) 사용 방식은 사이킷런 모델과 유사하다.

7.6 스태킹 (...쪽 또는 원서 p.208)

스태킹(stacking) 회귀

사이킷런의 StackingRegressor 모델

모델 훈련에 사용되는 데이터셋은 사이킷런의 혈당 관련 데이터이다.

10개의 특성은 다음과 같다.

특성 의미
age 만 나이
sex 성별
bmi 체질량지수(body mass index)
bp 평균 혈압
s1 tc 총콜레스테롤
s2 ldl 저밀도 콜레스테롤
s3 hdl 고밀도 콜레스테롤
s4 tch 총콜레스테롤/(고밀도 콜레스테롤)
s5 ltg 중성지방 수치의 로그값
s6 glu 혈당 수치

예측값은 1년 뒤의 당뇨병 진행도이다.

transform() 메서드는 훈련에 사용된 예측기별 예측값을 반환한다.

다층 스태킹(Multilayer Stacking) 회귀

스태킹 분류

사이킷런의 StackingClassifier 모델

연습문제 해답

1. to 7.

See Appendix A.

8. Voting Classifier

Exercise: Load the MNIST data and split it into a training set, a validation set, and a test set (e.g., use 50,000 instances for training, 10,000 for validation, and 10,000 for testing).

The MNIST dataset was loaded earlier.

Exercise: Then train various classifiers, such as a Random Forest classifier, an Extra-Trees classifier, and an SVM.

The linear SVM is far outperformed by the other classifiers. However, let's keep it for now since it may improve the voting classifier's performance.

Exercise: Next, try to combine them into an ensemble that outperforms them all on the validation set, using a soft or hard voting classifier.

Let's remove the SVM to see if performance improves. It is possible to remove an estimator by setting it to None using set_params() like this:

This updated the list of estimators:

However, it did not update the list of trained estimators:

So we can either fit the VotingClassifier again, or just remove the SVM from the list of trained estimators:

Now let's evaluate the VotingClassifier again:

A bit better! The SVM was hurting performance. Now let's try using a soft voting classifier. We do not actually need to retrain the classifier, we can just set voting to "soft":

Nope, hard voting wins in this case.

Once you have found one, try it on the test set. How much better does it perform compared to the individual classifiers?

The voting classifier only very slightly reduced the error rate of the best model in this case.

9. Stacking Ensemble

Exercise: Run the individual classifiers from the previous exercise to make predictions on the validation set, and create a new training set with the resulting predictions: each training instance is a vector containing the set of predictions from all your classifiers for an image, and the target is the image's class. Train a classifier on this new training set.

You could fine-tune this blender or try other types of blenders (e.g., an MLPClassifier), then select the best one using cross-validation, as always.

Exercise: Congratulations, you have just trained a blender, and together with the classifiers they form a stacking ensemble! Now let's evaluate the ensemble on the test set. For each image in the test set, make predictions with all your classifiers, then feed the predictions to the blender to get the ensemble's predictions. How does it compare to the voting classifier you trained earlier?

This stacking ensemble does not perform as well as the voting classifier we trained earlier, it's not quite as good as the best individual classifier.