튜토리얼
05. Ensemble Methods

05. Ensemble Methods

Bagging, Random Forest, Boosting, XGBoost, LightGBM


학습 목표

이 튜토리얼을 완료하면 다음을 할 수 있습니다:

  1. Bagging과 Boosting의 핵심 차이점 이해
  2. Random Forest의 동작 원리와 주요 파라미터 실험
  3. Gradient Boosting의 수학적 원리와 XGBoost 구현 이해
  4. XGBoost, LightGBM, CatBoost 성능 비교
  5. GridSearch, RandomSearch, Optuna를 활용한 하이퍼파라미터 튜닝
  6. Feature Importance 분석 및 모델 해석

핵심 개념

1. 앙상블이란?

앙상블 학습은 여러 개의 약한 학습기(Weak Learner)를 결합하여 강한 학습기(Strong Learner)를 만드는 기법입니다.

"세 사람의 지혜가 한 천재보다 낫다" - 집단지성
          ┌─────────────────────────────────────┐
          │         앙상블 학습 (Ensemble)        │
          └─────────────────────────────────────┘

          ┌───────────────┴───────────────┐
          ▼                               ▼
  ┌───────────────┐               ┌───────────────┐
  │    Bagging    │               │   Boosting    │
  │   (병렬 학습)   │               │   (순차 학습)   │
  └───────────────┘               └───────────────┘
          │                               │
          ▼                               ▼
  Random Forest               AdaBoost, GBM, XGBoost

2. 앙상블 유형

방법특징대표 모델
Bagging병렬 학습, 분산 감소Random Forest
Boosting순차 학습, 편향 감소XGBoost, LightGBM
Stacking메타 모델 학습StackingClassifier
Voting다수결/평균VotingClassifier

3. Bagging (Bootstrap Aggregating)

원리:

  1. 원본 데이터에서 Bootstrap 샘플링 (복원 추출)
  2. 각 샘플로 독립적인 모델 학습 (병렬 처리 가능)
  3. 예측 결과를 **투표(분류) 또는 평균(회귀)**으로 결합

수학적 표현:

f^bag(x)=1Bb=1Bf^b(x)\hat{f}_{bag}(x) = \frac{1}{B}\sum_{b=1}^{B}\hat{f}_b(x)

장점:

  • 분산(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

순차적으로 이전 모델의 오차를 보정하는 방식입니다.

원리:

  1. 첫 번째 모델 학습
  2. 이전 모델의 오차(Residual)에 집중하여 다음 모델 학습
  3. 모든 모델의 예측을 가중 합산

수학적 표현:

f^(x)=m=1Mγmhm(x)\hat{f}(x) = \sum_{m=1}^{M}\gamma_m h_m(x)

Gradient Boosting

손실 함수의 Gradient(기울기)를 이용하여 오차를 줄여나가는 방식:

Fm(x)=Fm1(x)+ηhm(x)F_m(x) = F_{m-1}(x) + \eta \cdot h_m(x)

여기서:

  • Fm(x)F_m(x): m번째 단계의 앙상블 예측
  • hm(x)h_m(x): m번째 약한 학습기 (잔차에 학습)
  • η\eta: 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 비교

특성XGBoostLightGBMCatBoost
트리 성장 방식Level-wiseLeaf-wiseLevel-wise
속도빠름매우 빠름보통
범주형 처리인코딩 필요지원강력한 지원
결측치 처리자동자동자동
GPU 지원YesYesYes
모델장점단점
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)
학습 방식병렬 (독립)순차 (의존)
목표분산 감소편향 + 분산 감소
과적합 위험낮음높음 (조심 필요)
학습 속도빠름 (병렬화)느림 (순차적)
튜닝 민감도낮음높음

면접 질문 맛보기

  1. Bagging과 Boosting의 차이점은?
  2. Random Forest에서 max_features의 역할은?
  3. 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