앙상블: 배깅 · 랜덤 포레스트 · 그래디언트 부스팅
부트스트랩 · OOB · 랜덤 포레스트 · AdaBoost · 그래디언트 부스팅을 손계산으로 익히는 앙상블 수업
먼저 알아야 할 것
다루는 내용
여러 모델을 모아 강한 모델을 만드는 앙상블을 다룹니다. 평균의 분산 공식으로 상관을 낮추는 것이 왜 중요한지 보이고, 부트스트랩에서 빠지는 비율(약 36.8%)과 OOB 평가, 랜덤 포레스트의 특성 무작위 선택을 설명합니다. AdaBoost 가중치 갱신과 제곱 오차 그래디언트 부스팅의 잔차 적합을 두 단계 손계산하고, scikit-learn 기본값과 배깅 · 부스팅 선택 기준을 정리합니다.
해설
앙상블: 배깅 · 랜덤 포레스트 · 그래디언트 부스팅
결정 트리 하나는 데이터가 조금만 바뀌어도 모양이 크게 달라지는 불안정한 모델입니다. 여러 모델을 모아 평균 내거나(배깅 · 랜덤 포레스트), 앞 모델이 틀린 부분을 다음 모델이 고치게 하면(부스팅) 훨씬 강한 모델이 됩니다. 이 수업은 부트스트랩 · OOB 평가 · 특성 무작위 선택 · AdaBoost 가중치 갱신 · 잔차를 맞추는 그래디언트 부스팅을 작은 숫자로 직접 계산합니다.
| 항목 | 내용 |
|---|---|
| 참고 자료 | scikit-learn 사용자 안내서 'Ensembles: Gradient boosting, random forests, bagging, voting, stacking' · scikit-learn.org/stable/modules/ensemble.html |
| 트랙 · 수준 | 머신러닝 · 중급 |
| 이 수업의 범위 | 앙상블의 원리, 부트스트랩 · 배깅, OOB 추정, 랜덤 포레스트, 특성 중요도, AdaBoost, 그래디언트 부스팅(잔차 적합), 학습률 · 트리 수, 히스토그램 기반 부스팅 |
| 먼저 알면 좋은 것 | 결정 트리의 분할(지니 · 제곱 오차), 분산의 뜻, 과적합 · 교차 검증 |
들어가기 전에
- 결정 트리: 지니 불순도 · 정보 이득 · 가지치기 — 앙상블의 부품은 거의 언제나 결정 트리입니다. 분할 기준과 깊이 제한을 알고 오면 됩니다.
- 모델 평가와 과적합 — 편향 · 분산, 검증 데이터, 교차 검증을 이 수업에서 계속 씁니다.
한눈에 보기
- 여러 모델을 평균 내면 왜 분산이 줄어드는지, 모델끼리 상관이 높으면 왜 효과가 줄어드는지 식으로 압니다.
- 부트스트랩 표본에 한 번도 뽑히지 않는 데이터가 약 36.8%라는 것과, 그 데이터로 하는 OOB 평가를 이해합니다.
- 랜덤 포레스트가 배깅에 "분할마다 특성 일부만 보기"를 더한 이유를 압니다.
- AdaBoost의 가중치 갱신과 그래디언트 부스팅의 잔차 맞추기를 손으로 두 단계 계산합니다.
- 배깅 계열과 부스팅 계열을 언제 고르는지, 어떤 하이퍼파라미터부터 만지는지 압니다.
1. 앙상블은 왜 강한가
직관(해설용 비유): 퀴즈 대회에서 한 사람에게 답을 맡기는 것보다, 서로 다른 공부를 한 열 명의 답을 다수결로 정하는 편이 대체로 더 잘 맞습니다. 단, 열 명이 모두 같은 참고서로 공부했다면 같은 문제를 같이 틀리므로 이득이 적습니다. 앙상블(ensemble)의 핵심은 "각자 쓸 만하면서 서로 다르게 틀리는" 모델을 모으는 것입니다.
앙상블은 크게 두 갈래입니다.
| 갈래 | 만드는 법 | 주로 줄이는 것 | 대표 |
|---|---|---|---|
| 평균 계열(averaging) | 서로 독립적으로 여러 모델을 학습해 평균 · 다수결 | 분산 | 배깅, 랜덤 포레스트 |
| 부스팅 계열(boosting) | 모델을 차례로 만들며 앞 모델의 약점을 보완 | 편향(그리고 분산도 일부) | AdaBoost, 그래디언트 부스팅 |
평균 내면 분산이 얼마나 줄어드나
모델 개의 예측 가 각각 분산 을 갖고, 서로 짝마다 상관계수가 라고 합시다. 평균 의 분산은 다음과 같습니다.
| 기호 | 뜻 |
|---|---|
| 모은 모델 수 | |
| 모델 하나의 예측 분산 | |
| 두 모델 예측 사이의 상관계수(0이면 서로 무관, 1이면 똑같음) |
유도는 간단합니다. 을 으로 나누면 위 식이 됩니다.
숫자로 해 보기(해설용): , , 이면 입니다. 모델을 아무리 늘려도() 분산은 아래로 내려가지 않습니다. 같은 조건을 난수 20만 번으로 모의실험해 보면 약 0.370이 나옵니다(파이썬으로 확인). 그래서 앙상블에서는 모델 수를 늘리는 것만큼 상관 를 낮추는 것이 중요합니다. 랜덤 포레스트의 특성 무작위 선택이 바로 를 낮추는 장치입니다.
2. 부트스트랩과 배깅
직관: 데이터는 한 벌뿐인데 서로 다른 모델을 여러 개 만들고 싶습니다. 그래서 원래 데이터에서 복원 추출(sampling with replacement)로 같은 크기의 표본을 여러 벌 만듭니다. 이것이 부트스트랩(bootstrap) 표본이고, 각 표본으로 모델을 하나씩 학습해 평균 · 다수결하는 방법이 배깅(bagging, bootstrap aggregating)입니다. Breiman이 1996년에 제안했습니다.
단계
- 데이터 개에서 복원 추출로 개를 뽑아 부트스트랩 표본을 만듭니다(같은 예제가 여러 번 뽑힐 수 있음).
- 표본마다 깊은 결정 트리를 하나씩 학습합니다.
- 회귀는 예측을 평균, 분류는 다수결(또는 확률 평균)로 합칩니다.
한 번도 안 뽑힐 확률: 특정 예제가 한 번 뽑기에서 빠질 확률은 이고, 번 모두 빠질 확률은
숫자로 해 보기(해설용): 이면 , 이면 약 , 이면 약 입니다. 즉 부트스트랩 표본 하나에는 원래 데이터의 약 63.2%만 (중복 포함해) 들어가고, 약 36.8%는 빠집니다.
OOB 추정: 공짜 검증 데이터
빠진 약 36.8%를 OOB(out-of-bag) 표본이라고 합니다. 각 예제에 대해 "그 예제를 학습에 안 쓴 트리들"만 모아 예측하면, 별도 검증 데이터 없이도 일반화 성능을 어림할 수 있습니다. scikit-learn에서는 oob_score=True로 켭니다. 다만 scikit-learn 안내서는 그래디언트 부스팅의 OOB 개선량 추정은 대체로 비관적이므로, 시간이 허락하면 교차 검증을 쓰라고 권합니다.
왜 깊은 트리를 쓰나: 배깅은 분산을 줄이는 방법이므로, 편향은 작고 분산이 큰 모델(가지치기 안 한 깊은 트리)과 궁합이 좋습니다. 원래 안정적인 모델(선형 회귀 등)은 배깅해도 얻는 것이 적습니다.
3. 랜덤 포레스트
직관: 배깅한 트리들은 여전히 비슷합니다. 아주 강한 특성 하나가 있으면 모든 트리가 맨 위에서 그 특성으로 나누기 때문입니다. 랜덤 포레스트(random forest, Breiman 2001)는 분할할 때마다 특성 중 일부만 무작위로 골라 그 안에서 최선의 분할을 찾게 해, 트리끼리의 상관 를 낮춥니다.
단계
- 부트스트랩 표본을 만듭니다(배깅과 같음).
- 트리를 키우면서, 노드마다 전체 특성 개 중 개를 무작위로 고르고 그 개 안에서만 분할을 찾습니다.
- 트리를 많이 만들어 합칩니다.
| 설정(scikit-learn 1.9 기본값) | 분류기 RandomForestClassifier | 회귀기 RandomForestRegressor |
|---|---|---|
트리 수 n_estimators | 100 | 100 |
분할마다 볼 특성 max_features | "sqrt" () | 1.0 (전부) |
부트스트랩 bootstrap | True | True |
깊이 max_depth | None(끝까지) | None |
숫자로 해 보기(해설용): 특성이 16개인 분류 문제라면 노드마다 개만 보고 분할합니다. 가장 강한 특성이 후보 4개 안에 들어올 확률은 이므로, 나머지 75%의 노드에서는 다른 특성이 기회를 얻습니다.
구현의 작은 차이: scikit-learn은 원 논문처럼 트리마다 한 표씩 투표하는 대신, 트리들의 확률 예측을 평균해 분류합니다(사용자 안내서에 명시).
특성 중요도: 랜덤 포레스트는 각 특성이 분할로 줄인 불순도의 합(MDI)으로 중요도를 줍니다. 값이 많은(연속형 · 고유값 많은) 특성을 과대평가하는 경향이 있으므로, 검증 데이터에서 특성 값을 섞어 성능 하락을 재는 순열 중요도(permutation importance)와 함께 보는 것이 안전합니다.
4. 부스팅 1: AdaBoost
직관: 오답 노트 공부법입니다. 첫 모델이 틀린 문제에 별표를 크게 치고, 다음 모델은 별표 친 문제를 더 신경 써서 공부합니다. AdaBoost(Freund · Schapire, 1995년 학회 발표 · 1997년 학술지)는 틀린 예제의 가중치를 올려 가며 약한 분류기(보통 깊이 1짜리 트리, 스텀프 stump)를 차례로 학습합니다.
단계(이진 분류, 원래 형태를 설명용으로 단순화)
- 모든 예제 가중치를 으로 시작합니다.
- 가중치를 반영해 약한 분류기 를 학습하고, 가중 오류율 를 잽니다.
- 분류기의 발언권 를 계산합니다.
- 틀린 예제 가중치는 배, 맞힌 예제는 배 한 뒤 합이 1이 되게 나눕니다.
- 최종 예측은 입니다.
| 기호 | 뜻 |
|---|---|
| 번째 분류기의 가중 오류율(0.5보다 작아야 쓸모 있음) | |
| 그 분류기의 발언권. 오류가 작을수록 큼 | |
| 번째 약한 분류기의 예측 |
숫자로 해 보기(해설용): 예제 5개, 처음 가중치는 모두 0.2입니다. 첫 스텀프가 1개를 틀려 라면 , , 입니다.
| 틀린 예제 1개 | 맞힌 예제 4개 | |
|---|---|---|
| 갱신 전 | 0.2 | 0.2씩 |
| 곱한 뒤 | 씩 | |
| 정규화(합 0.8로 나눔) | 0.5 | 0.125씩 |
틀린 예제 하나가 전체 가중치의 절반을 차지하게 됐습니다. 다음 스텀프는 이 예제를 맞히는 쪽으로 학습됩니다. scikit-learn의 AdaBoostClassifier는 다중 클래스로 넓힌 SAMME 방식(Zhu 외 2009)을 쓰며, 기본 약한 분류기는 깊이 1 트리, 기본 n_estimators는 50입니다.
5. 부스팅 2: 그래디언트 부스팅
직관: 골프에 비유하면, 첫 샷으로 홀 근처까지 보내고, 다음 샷은 "남은 거리"만큼 치고, 그다음도 남은 거리만큼 칩니다. 그래디언트 부스팅(gradient boosting, Friedman 2001)은 지금까지 모델이 못 맞힌 부분(잔차)을 다음 트리가 맞히게 해 예측을 조금씩 더해 갑니다.
단계(제곱 오차 회귀)
- 상수 예측 (평균)으로 시작합니다.
- 마다 잔차 를 계산합니다.
- 잔차를 맞히는 작은 트리 을 학습합니다.
- 로 조금만 더합니다.
| 기호 | 뜻 |
|---|---|
| 번째 단계까지 더한 전체 모델 | |
| 번째로 학습한 작은 트리 | |
| 학습률(shrinkage). 한 걸음을 얼마나 작게 걸을지 | |
| 손실 함수. 제곱 오차 이면 음의 기울기가 바로 잔차 |
"그래디언트"라는 이름은 둘째 식에서 옵니다. 다음 트리가 맞히는 대상은 손실의 음의 기울기이고, 제곱 오차에서는 그것이 잔차와 같습니다. 로그 손실 · 절대 오차 등 다른 손실도 같은 틀로 쓸 수 있다는 것이 이 방법의 힘입니다.
숫자로 해 보기(해설용, 파이썬으로 확인): , , 깊이 1 트리, 입니다.
- 시작: (평균). 평균 제곱 오차(MSE) .
- 1단계 잔차: . 가능한 분할 세 곳의 잔차 제곱합을 비교하면 : 8.67, : 10.0, : 2.0 → 로 나눕니다. 왼쪽 평균 , 오른쪽 평균 .
- 갱신: . MSE .
- 2단계 잔차: . 이번에는 와 가 둘 다 잔차 제곱합 2.0으로 동점이라 앞의 것(; 왼쪽 , 오른쪽 )을 고릅니다.
- 갱신: . MSE .
단계마다 오차가 줄어드는 모습이 보입니다. 이면 더 빨리 줄지만, 실제로는 작은 와 많은 트리를 쓰는 편이 새 데이터에서 더 잘 맞는 경우가 많습니다.
flowchart LR
A[학습 데이터] --> B[F0 = 평균]
B --> C[잔차 = 정답 - 현재 예측]
C --> D[잔차를 맞히는 작은 트리 학습]
D --> E[예측에 학습률 x 트리 출력 더하기]
E --> F{트리 수 M 도달 또는 검증 손실 정체?}
F -- 아니오 --> C
F -- 예 --> G[최종 모델 = F0 + 트리들의 합]하이퍼파라미터와 실무 선택
설정(scikit-learn 1.9 GradientBoostingClassifier 기본값) | 값 | 의미 |
|---|---|---|
learning_rate | 0.1 | 작을수록 트리가 더 많이 필요하지만 일반화가 좋아지는 경향 |
n_estimators | 100 | 트리 수. 학습률과 맞바꾸는 관계 |
max_depth | 3 | 트리 하나의 깊이. 특성 간 상호작용 차수를 정함 |
subsample | 1.0 | 1보다 작으면 단계마다 일부 데이터만 사용(확률적 그래디언트 부스팅, Friedman 2002) |
scikit-learn 안내서는 표본이 수만 개를 넘으면 특성 값을 구간(bin)으로 묶어 계산하는 HistGradientBoosting...이 기존 구현보다 몇 자릿수 빠를 수 있다고 설명합니다. 이 방식은 LightGBM에서 영감을 받았고, 정규화 항을 목적 함수에 넣는 방식은 다음 항목인 XGBoost와 닮았습니다.
왜 부스팅에는 얕은 트리를 쓰나: 부스팅은 편향을 줄여 가는 방법이므로, 부품 하나는 단순(편향 큼 · 분산 작음)해도 됩니다. 깊은 트리를 쓰면 몇 단계 만에 학습 데이터를 외워 과적합하기 쉽습니다. 배깅과 정반대의 선택입니다.
6. 배깅이냐 부스팅이냐
| 상황 | 먼저 고려할 것 | 이유 |
|---|---|---|
| 빠르게 튼튼한 기준선이 필요 | 랜덤 포레스트 | 기본값으로도 잘 작동, 튜닝이 적음, 병렬 학습 |
| 표 형태 데이터에서 최고 성능 | 그래디언트 부스팅(HistGB · XGBoost · LightGBM) | 편향을 끝까지 줄임, 대회 · 실무에서 강함 |
| 잡음 · 이상한 라벨이 많음 | 랜덤 포레스트 | 부스팅은 틀린 예제에 집중하므로 잘못된 라벨에 휘둘리기 쉬움 |
| 학습 시간이 짧아야 함 | 랜덤 포레스트(병렬) 또는 HistGB | 고전 그래디언트 부스팅은 순차 학습이라 느림 |
연습 문제
1. 데이터가 5개일 때, 특정 예제가 부트스트랩 표본에서 한 번도 뽑히지 않을 확률은?
풀이: , 약 32.8%입니다.
2. 모델 분산 , 상관 일 때, 모델 4개 평균과 무한히 많은 모델 평균의 분산은?
풀이: , 무한대에서는 입니다.
3. AdaBoost에서 가중 오류율이 0.1이면 는? 오류율 0.5이면?
풀이: . 0.5이면 으로 동전 던지기 수준이라 발언권이 없습니다.
4. 5절 예에서 로 1단계만 하면 과 MSE는?
풀이: . 오차 → MSE 입니다. 한 걸음에 크게 줄지만 그만큼 학습 데이터에 빠르게 맞춰집니다.
스스로 점검
- 랜덤 포레스트가 배깅보다 좋아지는 핵심 이유는?
- 답: 분할마다 특성 일부만 보게 해 트리끼리의 상관 를 낮추기 때문입니다. 평균의 분산 하한 가 내려갑니다.
- 그래디언트 부스팅의 "그래디언트"는 무엇의 기울기인가요?
- 답: 현재 예측 에 대한 손실의 기울기입니다. 다음 트리는 그 음의 기울기(제곱 오차에서는 잔차)를 맞힙니다.
- 배깅에는 깊은 트리, 부스팅에는 얕은 트리를 쓰는 이유는?
- 답: 배깅은 분산을 줄이므로 분산이 큰 깊은 트리가 알맞고, 부스팅은 편향을 차례로 줄이므로 단순한 트리를 많이 더하는 편이 과적합을 막습니다.
용어 정리
| 용어 | 쉬운 뜻 |
|---|---|
| 앙상블(ensemble) | 여러 모델의 예측을 합쳐 하나로 쓰는 방법 |
| 부트스트랩(bootstrap) | 원래 데이터에서 복원 추출로 같은 크기 표본을 만드는 것 |
| 배깅(bagging) | 부트스트랩 표본마다 모델을 학습해 평균 · 다수결 |
| OOB 표본(out-of-bag) | 어떤 부트스트랩 표본에 뽑히지 않은 데이터, 공짜 검증용 |
| 랜덤 포레스트(random forest) | 배깅 + 분할마다 특성 일부만 무작위로 보는 트리 앙상블 |
| 순열 중요도(permutation importance) | 특성 값을 섞었을 때 성능이 얼마나 떨어지는지로 잰 중요도 |
| 부스팅(boosting) | 앞 모델의 약점을 다음 모델이 보완하도록 차례로 쌓는 방법 |
| 스텀프(stump) | 깊이 1짜리 결정 트리 |
| AdaBoost | 틀린 예제 가중치를 올려 가며 약한 분류기를 쌓는 부스팅 |
| 잔차(residual) | 정답에서 현재 예측을 뺀 값 |
| 그래디언트 부스팅(gradient boosting) | 손실의 음의 기울기를 맞히는 트리를 더해 가는 부스팅 |
| 학습률 · 축소(learning rate · shrinkage) | 새 트리 출력을 얼마나 작게 더할지 정하는 계수 |
더 깊이 보려면
scikit-learn 사용자 안내서의 앙상블 장은 그래디언트 부스팅(히스토그램 기반 포함) · 랜덤 포레스트와 Extra-Trees · 배깅 · 투표 · 스태킹 · AdaBoost 순으로 구성되어 있고, 조기 종료 · 단조 제약 · 범주형 특성 처리 같은 실무 옵션을 자세히 다룹니다. 그래디언트 부스팅의 정규화 목적 함수와 분할 점수 공식은 다음 항목인 XGBoost 해설에서 이어집니다.
다음에 볼 것
- XGBoost: 확장 가능한 트리 부스팅 — 그래디언트 부스팅에 2차 근사와 정규화 항을 넣어 빠르고 강하게 만든 방법입니다.
- 군집화: k-평균 · 가우시안 혼합 · EM 알고리즘 — 라벨 없이 데이터의 묶음을 찾는 비지도 학습으로 넘어갑니다.
라이선스
이 글은 원문 번역이 아니라 KAITABASE가 직접 쓴 해설이며, 숫자 예는 모두 설명용으로 만든 것입니다(파이썬으로 다시 계산해 확인). 참고 자료인 scikit-learn 문서는 BSD-3-Clause 라이선스입니다.
출처
- 참고: scikit-learn.org/stable/modules/ensemble.… (scikit-learn 사용자 안내서 앙상블 장 — Breiman 1996 · 2001, Freund · Schapire, Friedman 2001 · 2002, LightGBM 인용, OOB · 확률 평균 · HistGB 설명)
- 기본값 확인: scikit-learn 1.9.0
RandomForestClassifier·RandomForestRegressor·AdaBoostClassifier·GradientBoostingClassifier생성자 서명과 문서 문자열(SAMME, Zhu 외 2009 인용)
AI 원리부터 이해하기 · 머신러닝 모듈
머신러닝 모듈 학습
이 글은 머신러닝 모듈의 학습 자료입니다. 전체 17개 자료 중 8번째입니다.
출처·원문
원문 보기요약만