앙상블 머신러닝: Random Forest와 Boosting은 어떻게 다를까?

Alchemist·5일 전

KT AIVLE

목록 보기
121/130

한 사람의 판단보다는 여러 사람의 판단을 모으면 더 안정적인 결론을 얻을 때가 있다. 머신러닝에서도 하나의 모델만 사용하는 대신 여러 모델의 예측을 결합하는 방법을 사용한다.

이 접근을 앙상블(Ensemble)이라고 한다. 대표적인 기법인 Bagging과 Boosting의 차이를 이해하면 Random Forest, Gradient Boosting 같은 모델을 쉽게 구분할 수 있다.

1. 앙상블은 왜 사용하는가?

결정트리 하나는 학습 데이터의 작은 변화에도 나무 구조가 크게 달라질 수 있다. 이런 모델을 여러 개 만든 다음 예측을 통합하면 개별 모델의 우연한 흔들림을 줄일 수 있다.

단, 여러 모델을 합치면 무조건 좋은 성능이 보장되는 것은 아니다. 모델 간 오류의 상관관계, 데이터 특성, 하이퍼파라미터가 모두 영향을 준다.

2. Bagging: 서로 다른 표본으로 여러 모델 학습

Bagging(Bootstrap Aggregating)은 데이터를 복원추출한 서로 다른 표본으로 여러 모델을 학습시킨 뒤, 그 예측을 모으는 방법이다.

원본 학습 데이터
    ├── 복원추출 표본 A → 모델 A ─┐
    ├── 복원추출 표본 B → 모델 B ─┼→ 예측 집계
    └── 복원추출 표본 C → 모델 C ─┘
  • 회귀: 일반적으로 예측값의 평균을 사용한다.
  • 분류: 다수결이나 클래스 확률의 평균을 사용할 수 있다.

복원추출은 한 데이터가 한 표본에 여러 번 등장할 수 있다는 뜻이다.

3. Random Forest의 두 가지 무작위성

Random Forest는 여러 결정트리를 결합하는 대표적인 Bagging 계열 모델이다.

특히 다음 두 요소가 핵심이다.

  1. 데이터 표본 무작위성: 트리마다 서로 다른 Bootstrap 표본을 사용한다.
  2. 변수 선택 무작위성: 각 노드에서 분할 후보가 되는 변수 일부를 무작위로 선택한다.

이렇게 만들면 모든 트리가 항상 똑같은 질문만 반복하는 현상을 줄이고, 다양한 판단을 모을 수 있다.

4. Random Forest 분류 모델 만들기

가상의 고객 지원 요청 데이터를 만들어 "사람의 추가 검토가 필요한가"를 분류해 보자.

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split

rng = np.random.default_rng(42)
n = 700

wait_minutes = rng.uniform(0, 90, n)
reopen_count = rng.integers(0, 6, n)
priority_score = rng.integers(1, 6, n)
text_length = rng.integers(20, 500, n)

risk = (
    -3.0
    + 0.025 * wait_minutes
    + 0.55 * reopen_count
    + 0.3 * priority_score
    + 0.001 * text_length
)
prob = 1 / (1 + np.exp(-risk))
need_review = rng.binomial(1, prob)

X = pd.DataFrame({
    "wait_minutes": wait_minutes,
    "reopen_count": reopen_count,
    "priority_score": priority_score,
    "text_length": text_length,
})
y = need_review

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)

model = RandomForestClassifier(
    n_estimators=200,
    max_depth=7,
    min_samples_leaf=3,
    random_state=42,
    n_jobs=-1,
)
model.fit(X_train, y_train)

pred = model.predict(X_test)
print(classification_report(y_test, pred, zero_division=0))

n_estimators=200은 트리 200개를 사용한다는 뜻이다. 많이 늘리면 성능이 안정되는 경우가 있지만 계산 비용도 커진다.

5. Random Forest의 주요 파라미터

이름역할
n_estimators트리의 개수
max_depth개별 트리 최대 깊이
min_samples_leaf리프에 필요한 최소 표본 수
max_features분할마다 고려하는 변수 수 또는 비율
bootstrap복원추출 사용 여부
class_weight클래스 가중치 설정
n_jobs병렬 처리 작업 수

트리 개수를 늘리는 것 외에도 개별 트리의 복잡도를 제어해야 한다.

6. 변수 중요도 확인

importance = pd.Series(
    model.feature_importances_,
    index=X.columns,
).sort_values(ascending=False)

print(importance)

Random Forest의 feature_importances_는 일반적으로 불순도 감소량에 기반한다. 따라서 값이 크다고 원인이라고 판단하면 안 되며, 범주가 많거나 연속적인 변수에 유리한 편향이 나타날 수도 있다.

검증 데이터에서 특정 변수만 섞은 뒤 예측 성능이 얼마나 떨어지는지 측정하는 permutation_importance()로 교차 확인할 수 있다.

from sklearn.inspection import permutation_importance

result = permutation_importance(
    model, X_test, y_test,
    n_repeats=5,
    random_state=42,
    scoring="f1",
)

print(pd.Series(result.importances_mean, index=X.columns).sort_values(ascending=False))

7. OOB(Out-of-Bag) 평가란?

Bootstrap 표본에 포함되지 않은 학습 데이터는 해당 트리의 예측을 검사하는 데 활용할 수 있다.

oob_model = RandomForestClassifier(
    n_estimators=200,
    oob_score=True,
    bootstrap=True,
    random_state=42,
)
oob_model.fit(X_train, y_train)

print("OOB score:", oob_model.oob_score_)

OOB는 별도 검증 점수에 대한 보조 정보가 될 수 있지만, 최종 테스트 데이터 평가를 대체하는 만능 지표는 아니다.

8. Boosting은 Bagging과 무엇이 다를까?

Boosting은 앞선 모델의 부족한 부분을 다음 모델이 보완해 가도록 모델을 순차적으로 결합하는 접근이다.

모델 1 → 남은 오차 또는 어려운 사례 확인
                  ↓
                모델 2
                  ↓
                모델 3 → 최종 결합

대표적으로 Gradient Boosting은 손실 함수를 낮추는 방향으로 새로운 모델을 순차적으로 추가한다.

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import f1_score

boosting = GradientBoostingClassifier(random_state=42)
boosting.fit(X_train, y_train)

print("Random Forest F1:", f1_score(y_test, model.predict(X_test)))
print("Gradient Boosting F1:", f1_score(y_test, boosting.predict(X_test)))

어느 쪽이 더 나은지는 데이터와 튜닝에 따라 달라진다. 위 코드는 동일한 데이터로 동작 차이를 체험하는 예시이며, 실제 모델 선택은 교차검증으로 수행하는 것이 적절하다.

9. XGBoost는 어떤 위치에 있을까?

XGBoost는 Gradient Boosting을 효율적으로 구현한 별도 라이브러리다. Scikit-learn에 기본 포함되어 있지 않으므로 사용할 때는 별도 설치가 필요하다.

pip install xgboost

단순히 RandomForestClassifier를 XGBClassifier로 바꾸기만 하면 항상 결과가 좋아지는 것은 아니다. 버전 호환성, 입력 데이터 처리, 평가 방식, 하이퍼파라미터를 함께 살펴봐야 한다.

10. 어떤 알고리즘을 우선 선택할까?

  • 결정트리: 판단 규칙을 직접 확인하고 설명하고 싶을 때
  • 랜덤 포레스트: 개별 트리의 변동성을 낮추고 강한 기본 성능을 얻고 싶을 때
  • Gradient Boosting: 단계적으로 오류를 보완하는 방식이 필요한 경우
  • XGBoost: 대규모 표 형식 데이터에 대한 최적화 옵션을 적극 활용하고 싶을 때

우선 간단한 기준 모델을 만들고, 같은 검증 방식으로 비교하는 것이 중요하다.

관련 공식 문서

핵심 정리

  • 앙상블은 여러 모델의 예측을 결합하는 방법이다.
  • Bagging은 보통 복원추출 표본별로 모델을 학습한 뒤 결과를 집계한다.
  • Random Forest는 여러 결정트리를 결합하며 표본과 변수 선택에 무작위성을 이용한다.
  • n_estimators는 트리 수, max_depth는 개별 트리의 복잡도를 제어한다.
  • OOB 점수는 Bootstrap에 포함되지 않은 관측치를 이용하는 보조 평가 방식이다.
  • Boosting은 이전 모델의 부족한 부분을 보완하는 방식으로 모델을 순차적으로 결합한다.
  • 불순도 기반 변수 중요도가 크다고 실제 원인이라고 단정할 수 없다.
  • Random Forest와 Boosting 중 어느 쪽이 좋은지는 데이터와 검증 결과가 결정한다.
profile
html_programming_language

0개의 댓글