XGBoost
Extreme Gradient Boosting
최적화된 그래디언트 부스팅 라이브러리. Kaggle 우승의 단골.
Extreme Gradient Boosting
최적화된 그래디언트 부스팅 라이브러리. Kaggle 우승의 단골.
XGBoost(eXtreme Gradient Boosting)는 Tianqi Chen이 개발한 최적화된 분산 그래디언트 부스팅 라이브러리입니다. 2014년에 공개된 이후, 정형 데이터(tabular data) 분석에서 딥러닝을 능가하는 성능으로 Kaggle 경진대회에서 수많은 우승을 차지했습니다. 결정 트리(Decision Tree)를 기본 학습기(base learner)로 사용하며, 앙상블 학습의 부스팅(Boosting) 방식으로 여러 약한 학습기를 순차적으로 학습시켜 강한 학습기를 만듭니다.
XGBoost의 핵심 혁신은 여러 가지입니다. 첫째, **정규화된 목적 함수**로 과적합을 방지합니다. L1(Lasso)과 L2(Ridge) 정규화를 트리 구조에 적용하여 모델 복잡도를 제어합니다. 둘째, **2차 테일러 근사**를 사용하여 손실 함수를 더 정확하게 최적화합니다. 기존 Gradient Boosting은 1차 도함수(gradient)만 사용했지만, XGBoost는 2차 도함수(Hessian)까지 활용합니다.
성능 최적화 측면에서도 탁월합니다. **히스토그램 기반 분할**로 연속형 변수를 구간(bin)으로 나누어 계산량을 크게 줄입니다. **열 블록(Column Block)** 구조로 데이터를 정렬된 상태로 저장하여 분할 계산 시 재정렬이 불필요합니다. **캐시 인식 접근(Cache-aware Access)**과 **Out-of-core 학습**으로 대용량 데이터도 효율적으로 처리합니다. CPU 멀티코어 병렬화와 GPU 학습도 지원합니다.
XGBoost는 분류, 회귀, 랭킹, 생존 분석 등 다양한 태스크를 지원하며, scikit-learn API와 호환됩니다. 결측치 자동 처리, 조기 종료(early stopping), 교차 검증, 피처 중요도 등 실무에 필요한 기능을 기본 제공합니다. LightGBM, CatBoost와 함께 "GBDT 3대장"으로 불리며, 정형 데이터 문제에서는 여전히 첫 번째 선택지입니다.
# XGBoost 분류 및 회귀 예제
import xgboost as xgb
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer, load_diabetes
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score, mean_squared_error
import matplotlib.pyplot as plt
# ============================================
# 1. 분류 문제 (Classification)
# ============================================
print("=" * 50)
print("분류 문제: 유방암 진단")
print("=" * 50)
# 데이터 로드
cancer = load_breast_cancer()
X_clf, y_clf = cancer.data, cancer.target
X_train, X_test, y_train, y_test = train_test_split(
X_clf, y_clf, test_size=0.2, random_state=42
)
# XGBoost 분류기 (scikit-learn API)
clf = xgb.XGBClassifier(
n_estimators=100, # 트리 개수
max_depth=6, # 트리 최대 깊이
learning_rate=0.1, # 학습률 (eta)
subsample=0.8, # 행 샘플링 비율
colsample_bytree=0.8, # 열 샘플링 비율
reg_alpha=0.1, # L1 정규화
reg_lambda=1.0, # L2 정규화
use_label_encoder=False,
eval_metric='logloss',
random_state=42
)
# 학습 (early stopping 포함)
clf.fit(
X_train, y_train,
eval_set=[(X_test, y_test)],
verbose=False
)
# 예측 및 평가
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"테스트 정확도: {accuracy:.4f}")
# 교차 검증
cv_scores = cross_val_score(clf, X_clf, y_clf, cv=5, scoring='accuracy')
print(f"5-Fold CV 정확도: {cv_scores.mean():.4f} (+/- {cv_scores.std()*2:.4f})")
# ============================================
# 2. 회귀 문제 (Regression)
# ============================================
print("\n" + "=" * 50)
print("회귀 문제: 당뇨병 진행도 예측")
print("=" * 50)
# 데이터 로드
diabetes = load_diabetes()
X_reg, y_reg = diabetes.data, diabetes.target
X_train_r, X_test_r, y_train_r, y_test_r = train_test_split(
X_reg, y_reg, test_size=0.2, random_state=42
)
# XGBoost 회귀 (Native API - DMatrix 사용)
dtrain = xgb.DMatrix(X_train_r, label=y_train_r)
dtest = xgb.DMatrix(X_test_r, label=y_test_r)
params = {
'objective': 'reg:squarederror',
'max_depth': 4,
'eta': 0.1,
'subsample': 0.8,
'colsample_bytree': 0.8,
'seed': 42
}
# Early stopping으로 학습
evals = [(dtrain, 'train'), (dtest, 'eval')]
model = xgb.train(
params,
dtrain,
num_boost_round=500,
evals=evals,
early_stopping_rounds=20,
verbose_eval=False
)
# 예측 및 평가
y_pred_r = model.predict(dtest)
rmse = np.sqrt(mean_squared_error(y_test_r, y_pred_r))
print(f"테스트 RMSE: {rmse:.4f}")
print(f"최적 반복 횟수: {model.best_iteration}")
# ============================================
# 3. 피처 중요도 분석
# ============================================
print("\n" + "=" * 50)
print("피처 중요도 (분류 모델)")
print("=" * 50)
# 피처 중요도 (gain, weight, cover)
importance_types = ['weight', 'gain', 'cover']
for imp_type in importance_types:
importance = clf.get_booster().get_score(importance_type=imp_type)
if importance:
sorted_imp = sorted(importance.items(), key=lambda x: x[1], reverse=True)[:5]
print(f"\n{imp_type.upper()} 기준 Top 5:")
for feat, score in sorted_imp:
print(f" {feat}: {score:.4f}")
# ============================================
# 4. 하이퍼파라미터 튜닝 가이드
# ============================================
print("\n" + "=" * 50)
print("하이퍼파라미터 튜닝 가이드")
print("=" * 50)
tuning_guide = """
1단계: 트리 구조 (과적합 제어)
- max_depth: 3~10 (깊을수록 복잡)
- min_child_weight: 1~10 (높을수록 보수적)
2단계: 샘플링 (분산 감소)
- subsample: 0.6~0.9 (행 샘플링)
- colsample_bytree: 0.6~0.9 (열 샘플링)
3단계: 정규화 (과적합 방지)
- reg_alpha (L1): 0~1
- reg_lambda (L2): 1~10
4단계: 학습률 및 트리 개수
- learning_rate: 0.01~0.3
- n_estimators: learning_rate와 반비례
"""
print(tuning_guide)
| 라이브러리 | 학습 속도 | 메모리 효율 | 범주형 변수 | GPU 지원 |
|---|---|---|---|---|
| XGBoost | 빠름 | 보통 | 수동 인코딩 | 지원 (CUDA) |
| LightGBM | 매우 빠름 | 우수 | 네이티브 지원 | 지원 |
| CatBoost | 빠름 | 보통 | 네이티브 지원 | 지원 |
| Random Forest | 보통 | 우수 | 수동 인코딩 | 미지원 |
성능 벤치마크 (100만 행, 100 피처 기준):
비용: 오픈소스 무료. AWS SageMaker XGBoost 빌트인 사용 시 ml.m5.xlarge 기준 시간당 약 $0.23
"정형 데이터니까 일단 XGBoost baseline부터 찍어보죠."
-> 정형 데이터 분석 시 기본 접근법
"early stopping 걸어서 과적합 막고, feature importance 뽑아봅시다."
-> 모델 학습 및 해석 논의 시
"max_depth 좀 줄이고 learning_rate 낮춰서 트리 수 늘려보세요."
-> 하이퍼파라미터 튜닝 조언 시
"범주형 변수가 많으면 CatBoost나 LightGBM이 나을 수도 있어요."
-> 라이브러리 선택 논의 시
학습 데이터에 검증 데이터 포함
early stopping용 eval_set에 학습 데이터를 넣으면 데이터 누수가 발생합니다. 반드시 별도의 검증 데이터를 사용하세요.
클래스 불균형 무시
불균형 데이터에서 scale_pos_weight 파라미터를 설정하지 않으면 다수 클래스에 편향됩니다. (음성/양성 비율로 설정)
과도한 max_depth
max_depth가 너무 크면(10 이상) 과적합 위험이 급격히 증가합니다. 보통 3~8 사이에서 시작하세요.
올바른 접근: 체계적인 튜닝
1) 기본값으로 baseline 확인 2) max_depth, min_child_weight 튜닝 3) subsample, colsample_bytree 튜닝 4) 정규화(alpha, lambda) 튜닝 5) learning_rate 낮추고 n_estimators 늘리기