05. Ensemble Methods
Bagging, Random Forest, Boosting, XGBoost, LightGBM
학습 목표
이 튜토리얼을 완료하면 다음을 할 수 있습니다:
- Bagging과 Boosting의 핵심 차이점 이해
- Random Forest의 동작 원리와 주요 파라미터 실험
- Gradient Boosting의 수학적 원리와 XGBoost 구현 이해
- XGBoost, LightGBM, CatBoost 성능 비교
- GridSearch, RandomSearch, Optuna를 활용한 하이퍼파라미터 튜닝
- Feature Importance 분석 및 모델 해석
핵심 개념
1. 앙상블이란?
앙상블 학습은 여러 개의 약한 학습기(Weak Learner)를 결합하여 강한 학습기(Strong Learner)를 만드는 기법입니다.
"세 사람의 지혜가 한 천재보다 낫다" - 집단지성 ┌─────────────────────────────────────┐
│ 앙상블 학습 (Ensemble) │
└─────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Bagging │ │ Boosting │
│ (병렬 학습) │ │ (순차 학습) │
└───────────────┘ └───────────────┘
│ │
▼ ▼
Random Forest AdaBoost, GBM, XGBoost2. 앙상블 유형
| 방법 | 특징 | 대표 모델 |
|---|---|---|
| Bagging | 병렬 학습, 분산 감소 | Random Forest |
| Boosting | 순차 학습, 편향 감소 | XGBoost, LightGBM |
| Stacking | 메타 모델 학습 | StackingClassifier |
| Voting | 다수결/평균 | VotingClassifier |
3. Bagging (Bootstrap Aggregating)
원리:
- 원본 데이터에서 Bootstrap 샘플링 (복원 추출)
- 각 샘플로 독립적인 모델 학습 (병렬 처리 가능)
- 예측 결과를 **투표(분류) 또는 평균(회귀)**으로 결합
수학적 표현:
장점:
- 분산(Variance) 감소 → Overfitting 방지
- 병렬 처리로 빠른 학습
- OOB(Out-of-Bag) 샘플로 검증 가능
OOB (Out-of-Bag) 인사이트: 각 Bootstrap 샘플에서 약 36.8%의 원본 데이터가 제외됩니다. 이 OOB 샘플을 이용하면 별도의 Validation Set 없이 성능 평가가 가능합니다!
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
bagging = BaggingClassifier(
estimator=DecisionTreeClassifier(),
n_estimators=100,
max_samples=0.8,
bootstrap=True,
oob_score=True, # OOB 점수 계산
random_state=42
)4. Random Forest
Random Forest = Bagging + Feature Randomness
- 각 트리 학습 시 랜덤하게 선택된 Feature 부분집합 사용
- 트리 간 상관관계 감소 → 앙상블 효과 극대화
주요 파라미터:
| 파라미터 | 설명 | 기본값 |
|---|---|---|
n_estimators | 트리 개수 (많을수록 좋지만 수확 체감) | 100 |
max_features | 각 분할에서 고려할 Feature 수 | sqrt(n) |
max_depth | 트리 최대 깊이 | None |
min_samples_split | 분할을 위한 최소 샘플 수 | 2 |
min_samples_leaf | 리프 노드의 최소 샘플 수 | 1 |
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(
n_estimators=100, # 트리 개수
max_depth=10, # 트리 깊이
max_features='sqrt', # 랜덤 피처 수
min_samples_leaf=2,
n_jobs=-1, # 병렬 처리
random_state=42
)n_estimators 선택 가이드: 트리가 늘어날수록 성능이 향상되지만 수확 체감이 발생합니다. OOB Score를 모니터링하면서 성능 향상이 멈추는 지점을 찾으세요. OOB Score와 Test Score가 유사하므로 별도 검증 세트 없이도 모델 선택이 가능합니다.
OOB (Out-of-Bag) Score
부트스트랩에 포함되지 않은 샘플로 검증:
rf = RandomForestClassifier(oob_score=True)
rf.fit(X_train, y_train)
print(f"OOB Score: {rf.oob_score_}")5. Boosting
순차적으로 이전 모델의 오차를 보정하는 방식입니다.
원리:
- 첫 번째 모델 학습
- 이전 모델의 오차(Residual)에 집중하여 다음 모델 학습
- 모든 모델의 예측을 가중 합산
수학적 표현:
Gradient Boosting
손실 함수의 Gradient(기울기)를 이용하여 오차를 줄여나가는 방식:
여기서:
- : m번째 단계의 앙상블 예측
- : m번째 약한 학습기 (잔차에 학습)
- : Learning rate (축소 계수)
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(
n_estimators=100,
learning_rate=0.1,
max_depth=3,
random_state=42
)XGBoost
from xgboost import XGBClassifier
xgb = XGBClassifier(
n_estimators=100,
learning_rate=0.1,
max_depth=3,
n_jobs=-1,
tree_method='hist', # 빠른 학습
random_state=42
)Early Stopping 활용: XGBoost에서는 early_stopping_rounds 파라미터로 조기 종료를 설정할 수 있습니다. 이를 통해 과적합을 방지하고 최적의 반복 횟수를 자동으로 찾을 수 있습니다.
# Early Stopping 예시
xgb_es = XGBClassifier(
n_estimators=1000, # 큰 값 설정
learning_rate=0.1,
early_stopping_rounds=20,
)
xgb_es.fit(
X_train, y_train,
eval_set=[(X_val, y_val)],
verbose=False
)
print(f"최적 반복 횟수: {xgb_es.best_iteration}")LightGBM
from lightgbm import LGBMClassifier
lgbm = LGBMClassifier(
n_estimators=100,
learning_rate=0.1,
max_depth=-1, # 제한 없음
num_leaves=31,
n_jobs=-1,
random_state=42
)6. XGBoost vs LightGBM vs CatBoost 비교
| 특성 | XGBoost | LightGBM | CatBoost |
|---|---|---|---|
| 트리 성장 방식 | Level-wise | Leaf-wise | Level-wise |
| 속도 | 빠름 | 매우 빠름 | 보통 |
| 범주형 처리 | 인코딩 필요 | 지원 | 강력한 지원 |
| 결측치 처리 | 자동 | 자동 | 자동 |
| GPU 지원 | Yes | Yes | Yes |
| 모델 | 장점 | 단점 |
|---|---|---|
| Random Forest | 병렬화, 과적합 방지, 튜닝 쉬움 | 느린 예측 |
| XGBoost | 높은 성능, 정규화 | 메모리 사용, 튜닝 민감 |
| LightGBM | 빠른 속도, 대용량 | Leaf-wise 과적합 |
| CatBoost | 범주형 처리 | 느린 학습 |
7. Feature Importance
# Random Forest
importances = rf.feature_importances_
# XGBoost (여러 유형)
xgb.feature_importances_ # gain 기반
import xgboost as xgb
xgb.plot_importance(model, importance_type='weight') # 분할 횟수
xgb.plot_importance(model, importance_type='gain') # 정보 이득
xgb.plot_importance(model, importance_type='cover') # 커버리지Feature Importance 해석 팁: 모델마다 Feature Importance가 다르게 계산됩니다. 여러 모델의 Importance를 종합하면 더 신뢰성 있는 해석이 가능합니다.
코드 요약
from sklearn.ensemble import (
RandomForestClassifier,
GradientBoostingClassifier,
VotingClassifier
)
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
# 모델들
models = {
'RF': RandomForestClassifier(n_estimators=100, random_state=42),
'GB': GradientBoostingClassifier(n_estimators=100, random_state=42),
'XGB': XGBClassifier(n_estimators=100, random_state=42),
'LGBM': LGBMClassifier(n_estimators=100, random_state=42)
}
# 성능 비교
for name, model in models.items():
scores = cross_val_score(model, X, y, cv=5)
print(f"{name}: {scores.mean():.4f} (+/-{scores.std():.4f})")Hyperparameter Tuning
GridSearchCV
from sklearn.model_selection import GridSearchCV
param_grid = {
'n_estimators': [100, 200],
'max_depth': [3, 5, 7],
'learning_rate': [0.01, 0.1, 0.2],
'subsample': [0.8, 1.0],
'colsample_bytree': [0.8, 1.0]
}
grid_search = GridSearchCV(
XGBClassifier(random_state=42),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"최적 파라미터: {grid_search.best_params_}")RandomizedSearchCV
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform, randint
param_distributions = {
'n_estimators': randint(50, 500),
'max_depth': randint(2, 10),
'learning_rate': uniform(0.01, 0.3),
'subsample': uniform(0.6, 0.4),
'colsample_bytree': uniform(0.6, 0.4)
}
random_search = RandomizedSearchCV(
XGBClassifier(random_state=42),
param_distributions,
n_iter=50,
cv=5,
n_jobs=-1
)
random_search.fit(X_train, y_train)Optuna 추천: 더 효율적인 하이퍼파라미터 튜닝을 위해 Optuna를 사용해보세요. TPE (Tree-structured Parzen Estimator) 샘플러를 사용하여 탐색 공간을 더 효과적으로 탐색합니다.
Voting Ensemble
여러 모델을 결합하여 추가 성능 향상을 얻을 수 있습니다:
from sklearn.ensemble import VotingClassifier
voting_clf = VotingClassifier(
estimators=[
('rf', RandomForestClassifier(n_estimators=200, random_state=42)),
('xgb', XGBClassifier(n_estimators=200, random_state=42)),
('lgb', LGBMClassifier(n_estimators=200, random_state=42))
],
voting='soft' # 확률 기반 투표
)
voting_clf.fit(X_train, y_train)앙상블 방법 체크리스트
| 항목 | Bagging (RF) | Boosting (XGB) |
|---|---|---|
| 학습 방식 | 병렬 (독립) | 순차 (의존) |
| 목표 | 분산 감소 | 편향 + 분산 감소 |
| 과적합 위험 | 낮음 | 높음 (조심 필요) |
| 학습 속도 | 빠름 (병렬화) | 느림 (순차적) |
| 튜닝 민감도 | 낮음 | 높음 |
면접 질문 맛보기
- Bagging과 Boosting의 차이점은?
- Random Forest에서 max_features의 역할은?
- XGBoost와 LightGBM의 차이점은?
더 많은 면접 질문은 Premium Interviews (opens in a new tab)에서 확인하세요.
실습 노트북
노트북에서 추가로 다루는 내용: Bootstrap Sampling 시각화, Bagging vs Single Tree 변동성 비교, n_estimators/max_features 효과 실험, Boosting 단계별 학습 과정 시각화, California Housing 데이터를 활용한 회귀 성능 비교, Optuna를 활용한 하이퍼파라미터 튜닝, 그리고 연습문제(House Prices 회귀, Stacking Ensemble, SHAP 분석)가 포함되어 있습니다.
이전: 04. Decision Tree | 다음: 06. Feature Engineering