본문으로 건너뛰기

048 랜덤 포레스트 회귀 상세

키워드: 랜덤 포레스트, 회귀

개요

랜덤 포레스트는 여러 결정 트리를 결합한 앙상블 알고리즘입니다. 회귀에서도 높은 성능과 안정성을 제공합니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: pycaret[full]>=3.0

랜덤 포레스트 회귀 원리

  1. 부트스트랩 샘플링으로 N개의 데이터셋 생성
  2. 각 데이터셋으로 결정 트리 학습 (무작위 특성 선택)
  3. 모든 트리의 예측값 평균으로 최종 예측
트리1: 예측값 = 25
트리2: 예측값 = 28
트리3: 예측값 = 24
...
트리N: 예측값 = 26

최종 예측 = (25 + 28 + 24 + ... + 26) / N

PyCaret에서 랜덤 포레스트 회귀

from pycaret.regression import *
from pycaret.datasets import get_data

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

# 048 랜덤 포레스트 회귀
rf = create_model('rf')

주요 하이퍼파라미터

# 048 n_estimators: 트리 개수
rf_100 = create_model('rf', n_estimators=100)
rf_200 = create_model('rf', n_estimators=200)

# 048 max_depth: 개별 트리 최대 깊이
rf_d10 = create_model('rf', max_depth=10)
rf_dnone = create_model('rf', max_depth=None) # 제한 없음

# 048 min_samples_split: 분할 최소 샘플
rf_split = create_model('rf', min_samples_split=10)

# 048 min_samples_leaf: 리프 최소 샘플
rf_leaf = create_model('rf', min_samples_leaf=5)

# 048 max_features: 분할 시 고려할 특성
rf_sqrt = create_model('rf', max_features='sqrt')
rf_log2 = create_model('rf', max_features='log2')
rf_third = create_model('rf', max_features=0.33)

# 048 bootstrap: 부트스트랩 사용 여부
rf_boot = create_model('rf', bootstrap=True)

n_estimators 영향

from pycaret.regression import *
from pycaret.datasets import get_data
import pandas as pd

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

results = []

for n_trees in [10, 50, 100, 200, 500]:
rf = create_model('rf', n_estimators=n_trees, verbose=False)
metrics = pull()

results.append({
'n_trees': n_trees,
'RMSE': metrics['RMSE'].mean(),
'R2': metrics['R2'].mean(),
'Std': metrics['RMSE'].std()
})

df = pd.DataFrame(results)
print(df)

# 100-200개면 충분, 더 늘려도 개선 미미

OOB Score

from pycaret.regression import *
from pycaret.datasets import get_data

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

# 048 OOB Score 활성화
rf = create_model('rf', oob_score=True, verbose=False)

print(f"OOB Score (R²): {rf.oob_score_:.4f}")

# 048 OOB Score ≈ 교차 검증 점수
# 048 별도 검증 세트 없이 성능 추정

특성 중요도

from pycaret.regression import *
from pycaret.datasets import get_data
import pandas as pd

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

rf = create_model('rf', verbose=False)

# 048 특성 중요도
feature_names = get_config('X_train').columns
importances = rf.feature_importances_

importance_df = pd.DataFrame({
'Feature': feature_names,
'Importance': importances
}).sort_values('Importance', ascending=False)

print("특성 중요도:")
print(importance_df)

# 048 시각화
plot_model(rf, plot='feature')

예측 불확실성

import numpy as np

# 048 개별 트리의 예측 분포로 불확실성 추정
X_test = get_config('X_test')

# 048 각 트리의 예측 수집
all_predictions = np.array([tree.predict(X_test) for tree in rf.estimators_])

# 048 평균과 표준편차
mean_pred = all_predictions.mean(axis=0)
std_pred = all_predictions.std(axis=0)

print(f"예측 불확실성 (평균 표준편차): {std_pred.mean():.4f}")

# 048 신뢰구간 계산
ci_lower = mean_pred - 1.96 * std_pred
ci_upper = mean_pred + 1.96 * std_pred

print(f"\n첫 5개 샘플의 95% 신뢰구간:")
for i in range(5):
print(f" 샘플 {i+1}: {mean_pred[i]:.2f} [{ci_lower[i]:.2f}, {ci_upper[i]:.2f}]")

튜닝

from pycaret.regression import *
from pycaret.datasets import get_data

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

rf = create_model('rf', verbose=False)

# 048 자동 튜닝
tuned_rf = tune_model(rf, optimize='RMSE')

# 048 커스텀 그리드
custom_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 5],
'max_features': ['sqrt', 'log2', 0.5]
}

tuned_rf = tune_model(rf, custom_grid=custom_grid, optimize='RMSE')

시각화

from pycaret.regression import *
from pycaret.datasets import get_data

data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)

rf = create_model('rf', verbose=False)

# 048 잔차 분석
plot_model(rf, plot='residuals')

# 048 예측 오차
plot_model(rf, plot='error')

# 048 특성 중요도
plot_model(rf, plot='feature')

# 048 학습 곡선
plot_model(rf, plot='learning')

장단점

장점:

  • 높은 예측 성능
  • 과적합에 강건
  • 특성 중요도 제공
  • 하이퍼파라미터 튜닝에 덜 민감
  • 병렬 처리 가능

단점:

  • 해석이 어려움 (블랙박스)
  • 메모리 사용량 높음
  • 외삽 불가
  • 실시간 예측에 부적합할 수 있음

랜덤 포레스트 vs 결정 트리

항목결정 트리랜덤 포레스트
과적합높음낮음
해석력높음낮음
성능보통높음
안정성낮음높음
학습 시간빠름보통
불확실성없음추정 가능

정리

  • 랜덤 포레스트는 여러 트리의 평균으로 예측
  • n_estimators=100~200이 일반적
  • max_features='sqrt' 또는 'log2' 권장
  • OOB Score로 별도 검증 없이 성능 추정
  • 개별 트리 예측으로 불확실성 추정 가능

다음 글 예고

다음 글에서는 Gradient Boosting 회귀 상세를 다룹니다.


PyCaret 머신러닝 마스터 시리즈 #048