본문 바로가기
머신러닝, 딥러닝

[머신러닝] 앙상블(ensemble) 학습

by 고경수 2023. 1. 17.

핸즈온 머신러닝을 공부한 내용을 정리하였습니다.

 

 

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

 

무작위로 선택된 수천 명의 사람에게 복잡한 질문을 하고 대답을 모은다고 가정하자.

많은 경우 이렇게 모은 답이 전문가의 답보다 낫다. 이를 대중의 지혜(wisdom of the crowd)라고 한다.

 

이와 비슷하게 일련의 예측기(즉, 분류나 회귀 모델)로부터 예측을 수집하면 가장 좋은 모델 하나보다 더 좋은 예측을 얻을 수 있을 것이다. 일련의 예측기를 앙상블이라고 부르기에 이를 앙상블 학습이라고 한다.

 

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

 

투표 기반 분류기

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

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

조금 놀랍게도 이 다수결 투표 분류기가 앙상블에 포함된 개별 분류기 중 가장 뛰어난 것보다도 정확도가 높을 경우가 많다. 이는 큰 수의 법칙(law of large number)(표본 집단의 크기가 커지면 표본 평균이 모평균에 가까워짐) 때문이다.

하지만 이런 가정은 모든 분류기가 완벽하게 독립적이고 오차에 상관관계가 없어야 가능하다.

 

< TIP >

앙상블 방법은 예측기가 가능한 한 서로 독립적일 때 최고의 성능을 발휘한다. 다양한 분류기를 얻는 한 가지 방법은 각기 다른 알고리즘으로 학습시키는 것이다. 이렇게 하면 매우 다른 종류의 오차를 만들 가능성이 높기 때문에 앙상블 모델의 정확도를 향상시킨다.

 

모든 분류기가 클래스의 확률을 예측할 수 있으면 (즉, predict_proba() 메서드가 있으면), 개별 분류기의 예측을 평균 내어 확률이 가장 높은 클래스를 에측할 수 있다. 이를 간접 투표(soft voting)이라고 한다. 이 방식은 확률이 높은 투표에 비중을 더 두기 때문에 직접 투표 방식보다 성능이 높다.

 

배깅과 페이스팅

다양한 분류기를 만드는 한 가지 방법은 각기 다른 훈련 알고리즘을 사용하는 것이다.

또 다른 방법은 같은 알고리즘을 사용하고 훈련 세트의 서브셋을 무작위로 구성하여 분류기를 각기 다르게 학습시키는 것이다. 훈련 세트에서 중복을 허용하여 샘플링하는 방식을 배깅(bagging) (bootstrap aggregating의 줄임말)이라 하며, 중복을 허용하지 않고 샘플링 하는 방식을 페이스팅(pasting)이라고 한다.

다시 말해 배깅과 페이스팅에서는 같은 훈련 샘플을 여러 개의 예측기에 걸쳐 사용할 수 있다.

하지만 배깅만이 한 예측기를 위해 같은 훈련 샘플을 여러 번 샘플링 할 수 있다.

 

모든 예측기가 훈련을 마치면 앙상블은 모든 예측기의 예측을 모아서 새로운 샘플에 대한 예측을 만든다. 수집 함수는 전형적으로 분류일 때는 통계적 최빈값이고 회귀에 대해서는 평균을 계산한다. 개별 예측기는 원본 훈련 세트로 훈련시킨 것보다 훨씬 크게 편향되어 있지만 수집 함수를 통과하면 편향과 분산이 모두 감소한다. 일반적으로 앙상블의 결과는 원본 데이터셋으로 하나의 예측기를 훈련시킬 때와 비교해 편향은 비슷하지만 분산은 줄어든다.

 

예측기는 모두 동시에 다른 CPU 코어나 서버에서 병렬로 학습시킬 수 있다. 이와 유사하게 예측도 병렬로 수행할 수 있다. 이런 확장성 덕분에 배깅과 페이스팅의 인기가 높다.

 

사이킷런의 배깅과 페이스팅

앙상블의 예측이 결정 트리 하나의 예측보다 일반화가 훨씬 잘된다.

앙상블은 비슷한 편향에서 더 작은 분산을 만든다 (훈련 세트의 오차 수가 거의 비슷하지만 결정 경계는 덜 불규칙하다)

 

부트스트래핑은 각 예측기가 학습하는 서브셋에 다양성을 증가시키므로 배깅이 페이스팅보다 편향이 조금 더 높다. 하지만 다양성을 추가한다는 것은 예측기들의 상관관계를 줄이므로 앙상블의 분산을 감소시킨다. 전반적으로 배깅이 더 나은 모델을 만들기 때문에 일반적으로 더 선호한다. 그러나 시간과 CPU 파워에 여유가 있다면 교차 검증으로 배깅과 페이스팅을 모두 평가해서 더 나은 쪽을 선택하는 것이 좋다.

 

oob 평가

배깅을 사용하면 어떤 샘플은 한 예측기를 위해 여러 번 샘플링되고 어떤 것은 전혀 선택되지 않을 수 있다.

BaggingClassifier는 기본값으로 중복을 허용하여(bootstrap=True) 훈련 세트의 크기만큼인 m개 샘플을 선택한다. 이는 평균적으로 각 예측기에 훈련 샘플의 63% 정도만 샘플링된다는 것을 의미한다. (m이 커지면 비율이 $1-\text{exp(-1)}\approx63.212\%$에 가까워 진다. m개의 샘플에서 무작위로 하나를 추출할 때 선택되지 않을 확률은 $1-\frac{1}{m}$이고 이를 m번 반복했을 때도 선택되지 않을 확률은 $(1-\frac{1}{m})^m$이다. 여기에 로그를 취하고 로피탈의 정리를 적용하면 이 값이 $e^{-1}$과 같아진다. 따라서 샘플링될 확률은 $1-\text{exp(-1)}\approx63.212\%$

선택되지 않은 훈련 샘플의 나머지 37%를 oob$^{\text{out-of-bag}}$샘플이라고 부른다. 예측기마다 남겨진 37%는 모두 다르다.

 

예측기가 훈련되는 동안에는 oob 샘플을 사용하지 않으므로 별도의 검증 세트를 사용하지 않고 oob 샘플을 사용해 평가할 수 있다. 앙상블의 평가는 각 예측기의 oob 평가를 평균하여 얻는다.

 

랜덤 패치와 랜덤 서브스페이스

BaggingClassifier는 특성 샘플링도 지원한다. 샘플링은 max_features, bootstrap_features 두 매개변수로 조절된다. 작동 방식은 max_samples, bootstrap과 동일하지만 샘플이 아니고 특성에 대한 샘플링이다. 따라서 각 예측기는 무작위로 선택한 입력 특성의 일부분으로 훈련된다.

 

이 기법은 특히 (이미지와 같은) 매우 고차원의 데이터셋을 다룰 때 유용하다.
    
훈련 특성과 샘플을 모두 샘플링하는 것을 랜덤 패치 방식$^{\text{random patches method}}$이라고 한다. 훈련 샘플을 모두 사용하고 특성은 샘플링하는 것을 랜덤 서브스페이스 방식$^{\text{random subspaces method}}$이라고 한다.
    
특성 샘플링은 더 다양한 예측기를 만들며 편향을 늘리는 대신 분산을 낮춘다.

 

랜덤 포레스트

랜덤 포레스트는 일반적으로 배깅 방법(또는 페이스팅)을 적용한 결정 트리의 앙상블이다.

 

랜덤 포레스트 알고리즘은 트리의 노드를 분할할 때 전체 특성 중에서 최선의 특성을 찾는 대신 무작위로 선택한 특성 후보 중에서 최적의 특성을 찾는 식으로 무작위성을 더 주입한다.

 

이는 결국 트리를 다양하게 만들고 (다시 한번) 편향을 손해보는 대신 분산을 낮추어 전체적으로 더 훌륭한 모델을 만들어낸다.

 

엑스트라 트리 *

랜덤 포레스트에서 트리를 만들 때 각 노드는 무작위로 특성의 서브셋을 만들어 분할에 사용한다. 트리를 더욱 무작위하게 만들기 위해 (보통의 결정 트리처럼) 최적의 임곗값을 찾는 대신 후보 특성을 사용해 무작위로 분할한 다음 그중에서 최상의 분할을 선택한다.여기서도 역시 편향이 늘어나지만 대신 분산을 낮추게 된다. 모든 노드에서 특성마다 가장 최적의 임곗값을 찾는 것이 트리 알고리즘에서 가장 시간이 많이 소요되는 작업 중 하나이므로 일반적인 랜덤 포레스트보다 엑스트라 트리가 훨씬 빠르다.

 

이와 같이 극단적으로 무작위한 트리의 랜덤 포레스트를 익스트림 랜덤 트리$^{\text{extremely randomized trees}}$ 앙상블(또는 줄여서 엑스트라 트리$^{\text{extra-trees}}$)이라고 부른다.

 

여기서도 역시 편향이 늘어나지만 대신 분산을 낮추게 된다. 모든 노드에서 특성마다 가장 최적의 임곗값을 찾는 것이 트리 알고리즘에서 가장 시간이 많이 소요되는 작업 중 하나이므로 일반적인 랜덤 포레스트보다 엑스트라 트리가 훨씬 빠르다.

 

특성 중요도

랜덤 포레스트의 또 다른 장점은 특성의 상대적 중요도를 측정하기 쉽다는 것이다.(결정 트리를 기반으로 하는 모델은 모두 특성 중요도를 제공한다)

 

사이킷런은 어떤 특성을 사용한 노드가 (랜덤 포레스트에 있는 모든 트리에 걸쳐서) 평균적으로 불순도를 얼마나 감소시키는지 확인하여 특성의 중요도를 측정한다. 더 정확히 말하면 가중치 평균이며 각 노드의 가중치는 연관된 훈련 샘플 수와 같다.

 

랜덤 포레스트는 특히 특성을 선택해야 할 때 어떤 특성이 중요한지 빠르게 확인할 수 있어 매우 편리하다.

 

부스팅 *

부스팅$^{\text{boosting}}$은 약한 학습기를 여러 개 연결하여 강한 학습기를 만드는 앙상블 방법을 말한다.

 

부스팅 방법의 아이디어는 앞의 모델을 보완해나가면서 일련의 예측기를 학습시키는 것이다.

 

부스팅 방법에는 여러 가지가 있지만 가장 인기 있는 것은 에이다부스트$^{\text{AdaBoost}}$(adaptive boosting의 줄임말)와 그레이디언트 부스팅$^{\text{gradient boosting}}$이다.

 

에이다부스트

이전 예측기를 보완하는 새로운 예측기를 만드는 방법은 이전 모델이 과소적합했던 훈련 샘플의 가중치를 더 높이는 것이다. 이렇게 하면 새로운 예측기는 학습하기 어려운 샘플에 점점 더 맞춰지게 된다. 이것이 에이다부스트에서 사용하는 방식이다.

 

예를 들어 에이다부스트 분류기를 만들 때 먼저 알고리즘이 기반이 되는 첫 번째 분류기 (예를 들면 결정 트리)를 훈련 세트에서 훈련시키고 예측을 만든다. 그 다음에 알고리즘이 잘못 분류된 훈련 샘플의 가중치를 상대적으로 높인다. 두 번째 분류기는 업데이트된 가중치를 사용해 훈련 세트에서 훈련하고 다시 예측을 만든다. 그다음에 다시 가중치를 업데이트하는 식으로 계속된다.

 

이런 연속된 학습 기법은 경사 하강법과 비슷한 면이 있다. 경사 하강법은 비용 함수를 최소화하기 위해 한 예측기의 모델 파라미터를 조정해가는 반면 에이다부스트는 점차 더 좋아지도록 앙상블에 예측기를 추가한다.

 

모든 예측기가 훈련을 마치면 이 앙상블은 배깅이나 페이스팅과 비슷한 방식으로 예측을 만든다. 하지만 가중치가 적용된 훈련 세트의 전반적인 정확도에 따라 예측기마다 다른 가중치가 적용된다.

 

CAUTION

연속된 학습 기법에는 중요한 단점이 하나 있다. 각 예측기는 이전 예측기가 훈련되고 평가된 후에 학습될 수 있기 때문에 병렬화(또는 분할)를 할 수 없다. 결국 배깅이나 페이스팅만큼 확장성이 높지 않다.

 

그레이디언트 부스팅

에이다부스트처럼 그레이디언트 부스팅은 앙상블에 이전까지의 오차를 보정하도록 예측기를 순차적으로 추가한다. 하지만 에이다부스트처럼 반복마다 샘플의 가중치를 수정하는 대신 이전 예측기가 만든 잔여 오차$^{\text{residual error}}$에 새로운 예측기를 학습시킨다.

 

learning_rate 매개변수가 각 트리의 기여 정도를 조절한다. 이를 0.1처럼 낮게 설정하면 앙상블은 훈련 세트에 학습시키기 위해 많은 트리가 필요하지만 일반적으로 예측의 성능은 좋아진다. 이는 **축소$^{\text{shrinkage}}$**라고 부르는 규제 방법이다.

 

최적화된 그레이디언트 부스팅 구현으로 XGBoost 파이썬 라이브러리가 유명하다.

 

XGBoost는 익스트림 그레이디언트 부스팅$^{\text{extreme gradient boosting}}$의 약자이다. 이 패키지의 목표는 매우 빠른 속도, 확장성, 이식성이다. 이는 머신러닝 경연 대회에서 우승 후보들이 사용하는 중요 도구 중 하나이다.

 

스태킹 *

스태킹$^{\text{stacking}}$(stacked generalization의 줄임말)

‘앙상블에 속한 모든 예측기의 예측을 취합하는 간단한 함수(직접 투표 같은)를 사용하는 대신 취합하는 모델을 훈련시킬 수 없을까?’라는 기본 아이디어로 출발

 

여러 예측기는 각각 다른 값을 예측하고 마지막 예측기 (블렌더(blender) 또는 메타 학습기(meta learner)라고한다)가 이 예측을 입력으로 받아 최종 예측을 만든다.

 

블렌더를 학습시키는 일반적인 방법은 홀드 아웃$^{\text{hold-out}}$ 세트를 사용하는 것입니다.

먼저 훈련 세트를 두개의 서브셋으로 나눈다. 첫 번째 서브셋은 첫 번째 레이어의 예측을 훈련시키기 위해 사용된다.

그런 다음 첫 번째 레이어의 예측기를 사용해 두 번째 (홀드 아웃) 세트에 대한 예측을 만든다.

 

예측기들이 훈련하는 동안 이 샘플들을 전혀 보지 못했기 때문에 이때 만들어진 예측은 완전히 새로운 것이다. 홀드 아웃 세트의 각 샘플에 대해 세 개(임의 숫자 설정)의 예측값이 있다.

 

타깃값은 그대로 쓰고 앞에서 예측한 값을 입력 특성으로 사용하는 새로운 훈련 세트를 만들 수 있다(새로운 훈련 세트는 3차원이 된다). 블렌더가 새 훈련 세트로 훈련된다.

 

즉, 첫 번째 레이어의 예측을 가지고 타깃값을 예측하도록 학습된다.

'머신러닝, 딥러닝' 카테고리의 다른 글

[Pytorch] 파이토치 사전학습 모델 사용법  (0) 2023.05.15