🤖 AI/ML

랜덤 포레스트

Random Forest

다수의 결정 트리를 앙상블하는 기법. 과적합에 강함.

📖 상세 설명

랜덤 포레스트(Random Forest)는 다수의 결정 트리(Decision Tree)를 학습시킨 후, 각 트리의 예측을 종합하여 최종 결과를 도출하는 앙상블(Ensemble) 학습 방법입니다. 분류 문제에서는 다수결 투표, 회귀 문제에서는 평균값을 사용하여 예측하며, 단일 결정 트리보다 훨씬 안정적인 성능을 보입니다.

2001년 Leo Breiman이 제안한 랜덤 포레스트는 배깅(Bagging)과 피처 랜덤화를 결합한 알고리즘입니다. 각 트리는 전체 데이터에서 복원 추출된 부트스트랩 샘플로 학습되고, 노드 분할 시 전체 피처가 아닌 무작위로 선택된 일부 피처만 고려합니다. 이 과정이 트리 간 상관관계를 줄여 과적합을 방지합니다.

랜덤 포레스트의 핵심 원리는 "약한 학습기들의 집단 지성"입니다. 개별 트리는 과적합되기 쉽지만, 수백 개의 트리가 서로 다른 데이터와 피처로 학습하면 오류가 상쇄됩니다. 피처 중요도(Feature Importance)를 계산할 수 있어 모델 해석성도 뛰어나며, OOB(Out-of-Bag) 에러로 별도 검증 세트 없이 성능을 추정할 수 있습니다.

2024-2025년에도 랜덤 포레스트는 정형 데이터 분석의 핵심 알고리즘으로 활용됩니다. Kaggle 대회에서 XGBoost, LightGBM과 함께 Top 3 솔루션의 필수 구성요소이며, 금융 사기 탐지, 의료 진단, 신용 평가 등 해석 가능성이 중요한 도메인에서 특히 선호됩니다. scikit-learn의 RandomForestClassifier는 월간 1억 회 이상 사용됩니다.

💻 코드 예제

# 랜덤 포레스트 분류 및 피처 중요도 분석
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
import pandas as pd
import numpy as np

# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names

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

# 랜덤 포레스트 모델 생성
rf = RandomForestClassifier(
    n_estimators=100,      # 트리 개수
    max_depth=10,          # 최대 깊이
    min_samples_split=5,   # 분할 최소 샘플
    max_features='sqrt',   # 피처 선택: sqrt(n_features)
    oob_score=True,        # OOB 점수 계산
    random_state=42,
    n_jobs=-1              # 병렬 처리
)

# 학습 및 평가
rf.fit(X_train, y_train)

print(f"테스트 정확도: {rf.score(X_test, y_test):.4f}")
print(f"OOB 점수: {rf.oob_score_:.4f}")

# 교차 검증
cv_scores = cross_val_score(rf, X, y, cv=5)
print(f"5-Fold CV: {cv_scores.mean():.4f} (+/- {cv_scores.std()*2:.4f})")

# 피처 중요도 분석
importance_df = pd.DataFrame({
    'feature': feature_names,
    'importance': rf.feature_importances_
}).sort_values('importance', ascending=False)

print("\n📊 피처 중요도:")
for _, row in importance_df.iterrows():
    bar = '█' * int(row['importance'] * 50)
    print(f"  {row['feature']:20s} {row['importance']:.3f} {bar}")

🗣️ 실무에서 이렇게 말하세요

💬 회의에서
"고객 이탈 예측 모델은 랜덤 포레스트로 시작하죠. 해석 가능성도 좋고, OOB 스코어로 빠르게 성능 확인할 수 있어서요. 피처 중요도 보면 어떤 요인이 이탈에 영향 주는지 바로 파악됩니다."
💬 면접에서
"랜덤 포레스트가 과적합에 강한 이유는 배깅과 피처 랜덤화 덕분입니다. 각 트리가 부트스트랩 샘플로 학습하고, 노드 분할 시 sqrt(n_features)개만 고려해서 트리 간 상관관계를 줄입니다. 결과적으로 분산이 감소해 일반화 성능이 좋아집니다."
💬 기술 토론에서
"XGBoost가 성능은 더 나올 수 있지만, 규제 산업에서는 랜덤 포레스트를 선호합니다. EU AI Act 기준으로 설명 가능성이 중요하거든요. SHAP 적용해서 개별 예측 설명도 가능하고요."

⚠️ 흔한 실수 & 주의사항

트리 개수(n_estimators)만 늘리면 무조건 좋다

100개 이상에서는 성능 향상이 미미하고 학습 시간만 길어집니다. 보통 100-500개가 적정하며, OOB 에러 수렴 여부로 판단하세요.

불균형 데이터에서 기본 설정 사용

랜덤 포레스트는 다수 클래스에 편향됩니다. class_weight='balanced' 또는 SMOTE 같은 오버샘플링을 적용해야 합니다.

올바른 방법

n_estimators=100부터 시작, max_depth로 과적합 제어, 불균형 시 class_weight 조정. 피처 중요도와 SHAP으로 모델 해석하고, 교차 검증으로 성능 검증하세요.

🔗 관련 용어

📚 더 배우기