본문으로 건너뛰기

049 Gradient Boosting 회귀 상세

키워드: Gradient Boosting, 회귀

개요

Gradient Boosting은 약한 학습기를 순차적으로 결합하는 앙상블 기법입니다. 회귀에서 잔차를 반복적으로 줄여나가며 강력한 예측 모델을 구축합니다.

실습 환경

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

Gradient Boosting 회귀 원리

  1. 초기 모델: 타겟의 평균값으로 예측
  2. 잔차(실제 - 예측) 계산
  3. 잔차를 예측하는 새 트리 학습
  4. 기존 모델에 새 트리 추가 (learning_rate로 가중)
  5. 2-4 반복
F₀(x) = 평균값
잔차₁ = y - F₀(x)
h₁(x) = 잔차₁ 예측 트리
F₁(x) = F₀(x) + η × h₁(x)
...

PyCaret에서 Gradient Boosting 회귀

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

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

# 049 Gradient Boosting 회귀
gbr = create_model('gbr')

주요 하이퍼파라미터

# 049 n_estimators: 부스팅 단계 수
gbr_100 = create_model('gbr', n_estimators=100)
gbr_200 = create_model('gbr', n_estimators=200)

# 049 learning_rate: 각 트리의 기여도
gbr_lr01 = create_model('gbr', learning_rate=0.1)
gbr_lr005 = create_model('gbr', learning_rate=0.05)

# 049 max_depth: 개별 트리 깊이
gbr_d3 = create_model('gbr', max_depth=3)
gbr_d5 = create_model('gbr', max_depth=5)

# 049 subsample: 샘플 비율
gbr_sub = create_model('gbr', subsample=0.8)

# 049 min_samples_split, min_samples_leaf
gbr_split = create_model('gbr', min_samples_split=10)

Learning Rate와 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)

configs = [
{'learning_rate': 0.1, 'n_estimators': 100},
{'learning_rate': 0.05, 'n_estimators': 200},
{'learning_rate': 0.01, 'n_estimators': 500},
]

results = []

for config in configs:
gbr = create_model('gbr', **config, verbose=False)
metrics = pull()

results.append({
'lr': config['learning_rate'],
'n_est': config['n_estimators'],
'RMSE': metrics['RMSE'].mean(),
'R2': metrics['R2'].mean()
})

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

# 049 learning_rate 낮추고 n_estimators 높이면 성능 향상 (시간 증가)

Staged Predict

import matplotlib.pyplot as plt
import numpy as np

# 049 학습 단계별 성능 추적
gbr = create_model('gbr', n_estimators=200, verbose=False)

X_test = get_config('X_test')
y_test = get_config('y_test')

# 049 각 단계별 RMSE
staged_scores = []
for y_pred in gbr.staged_predict(X_test):
rmse = np.sqrt(np.mean((y_test - y_pred) ** 2))
staged_scores.append(rmse)

plt.figure(figsize=(10, 6))
plt.plot(range(1, len(staged_scores) + 1), staged_scores)
plt.xlabel('Number of Trees')
plt.ylabel('RMSE')
plt.title('Gradient Boosting: RMSE vs Number of Trees')
plt.grid(True)
plt.savefig('gbr_staged_rmse.png', dpi=150)

손실 함수

# 049 loss: 손실 함수 선택
gbr_ls = create_model('gbr', loss='squared_error') # 기본값, MSE
gbr_lad = create_model('gbr', loss='absolute_error') # MAE, 이상치에 강건
gbr_huber = create_model('gbr', loss='huber') # Huber, 절충안
gbr_quantile = create_model('gbr', loss='quantile', alpha=0.5) # 분위수 회귀

Huber 손실

이상치에 강건한 손실 함수:

from pycaret.regression import *
from pycaret.datasets import get_data
import numpy as np

# 049 이상치가 있는 데이터 시뮬레이션
data = get_data('boston')

# 049 일부 이상치 추가
data_outlier = data.copy()
outlier_idx = np.random.choice(len(data), 20, replace=False)
data_outlier.loc[outlier_idx, 'medv'] *= 3 # 가격 3배

reg = setup(data_outlier, target='medv', session_id=42, verbose=False)

# 049 일반 MSE
print("=== Squared Error (MSE) ===")
gbr_mse = create_model('gbr', loss='squared_error')

# 049 Huber 손실 (이상치에 강건)
print("\n=== Huber Loss ===")
gbr_huber = create_model('gbr', loss='huber', alpha=0.9)

튜닝

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

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

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

# 049 자동 튜닝
tuned_gbr = tune_model(gbr, optimize='RMSE')

# 049 커스텀 그리드
custom_grid = {
'n_estimators': [100, 200, 300],
'learning_rate': [0.01, 0.05, 0.1],
'max_depth': [3, 4, 5],
'subsample': [0.8, 0.9, 1.0],
'min_samples_split': [2, 5, 10]
}

tuned_gbr = tune_model(gbr, custom_grid=custom_grid, optimize='RMSE')

특성 중요도

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)

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

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

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

print(importance_df)

plot_model(gbr, plot='feature')

장단점

장점:

  • 매우 높은 예측 성능
  • 다양한 손실 함수 지원
  • 특성 중요도 제공
  • 이상치 처리 가능 (Huber)

단점:

  • 학습 시간 오래 걸림
  • 순차적 학습 (병렬화 어려움)
  • 하이퍼파라미터 튜닝 필요
  • 과적합 위험 (early stopping 필요)

Gradient Boosting vs Random Forest

항목Gradient BoostingRandom Forest
학습 방식순차적병렬
과적합위험 높음위험 낮음
튜닝민감함덜 민감
속도느림빠름
최종 성능보통 더 높음좋음

정리

  • Gradient Boosting은 잔차를 순차적으로 줄여나감
  • learning_rate와 n_estimators의 균형이 중요
  • Huber 손실로 이상치에 대응
  • XGBoost, LightGBM이 더 빠르고 효율적
  • 튜닝이 성능에 큰 영향

다음 글 예고

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


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