CatBoost

코딩다시시작·2025년 3월 4일

LG DX SCHOOL

목록 보기
12/33

CatBoost: 이론, 수식, 실전 적용

1. 개요

CatBoost란?

범주형 데이터(categorical features) 처리에 강점을 가짐.

Gradient Boosting 알고리즘들은 반복적으로 트리를 학습하면서 성능을 향상시키는 방식으로 동작함.
기존 부스팅 모델(XGBoost, LightGBM 등)은 Target Leakage(타깃 누출) 및 Prediction Shift(예측값 분포 이동) 문제를 가짐.
CatBoost는 이를 해결하기 위해 Ordered Target Statistics (OTS) 및 Ordered Boosting 기법을 도입함.


2. Gradient Boosting 개념

Gradient Boosting이란?

  • Gradient Boosting은 여러 개의 약한 학습기(Weak Learner, 보통 결정 트리)를 순차적으로 학습하여 성능을 점진적으로 향상시키는 앙상블 학습 기법

  • 일반적으로 잔차(residuals)를 줄이는 방향으로 새로운 트리를 추가하며, 반복적인 업데이트 과정을 통해 최적의 모델을 구축

기본 수식

  1. 초기 예측값 설정:

    F0(x)=E[y]F^0(x) = \mathbb{E}[y]

    모델의 초기 예측값은 타깃의 평균값으로 설정됨.

  2. 이후 업데이트 단계:

    Ft(x)=Ft−1(x)+αht(x)F^t(x) = F^{t-1}(x) + \alpha h_t(x)

    ht(x)h_t(x)는 새롭게 추가되는 트리, α\alpha는 학습률 (Learning Rate)이며, 각 단계에서 모델이 오차를 보정하는 방향으로 업데이트됨.

  3. 각 단계에서 새로운 트리는 기존 모델의 잔차(residuals)를 최소화하는 방향으로 학습됨:

    ht=arg⁡min⁡h∑i=1nL(yi,Ft−1(xi)+h(xi))h_t = \arg \min_{h} \sum_{i=1}^{n} L(y_i, F^{t-1}(x_i) + h(x_i))

    손실 함수 L(y,y^)L(y, \hat{y})를 최적화함.


3. 기존 Gradient Boosting 문제점

Target Leakage(타깃 누출) 문제

기존 Target Statistics 방식

범주형 변수를 수치형으로 변환할 때, 전통적인 방법은 해당 범주 내 샘플들의 평균 타깃값을 사용하는 방식임.

x^ki=∑j=1n1{xji=xki}⋅yj+ap∑j=1n1{xji=xki}+a\hat{x}_{k}^{i} = \frac{\sum_{j=1}^{n} 1\{x_j^i = x_k^i\} \cdot y_j + a p}{\sum_{j=1}^{n} 1\{x_j^i = x_k^i\} + a}
  • yjy_j는 타깃값
  • pp는 전체 평균 타깃값
  • aa는 스무딩(Smoothing) 파라미터
  • 해당 샘플의 타깃 값이 변환 과정에 포함되므로 타깃 누출이 발생함.

CatBoost의 해결책: Ordered Target Statistics (OTS)

CatBoost는 이를 해결하기 위해 순서 기반 타깃 통계(Ordered Target Statistics, OTS) 기법을 사용함.

x^ki=∑xj∈Dk1{xji=xki}⋅yj+ap∑xj∈Dk1{xji=xki}+a\hat{x}_{k}^{i} = \frac{\sum_{x_j \in D_k} 1\{x_j^i = x_k^i\} \cdot y_j + a p}{\sum_{x_j \in D_k} 1\{x_j^i = x_k^i\} + a}
  • DkD_k는 현재 샘플보다 앞선 데이터만 포함하는 집합임.
  • 훈련 데이터를 랜덤한 순서로 정렬하고, 해당 샘플의 변환값을 계산할 때 과거 데이터만을 활용하여 타깃 누출을 방지함.

Prediction Shift(예측값 분포 이동) 문제

기존 Gradient Boosting 방식

기존 Gradient Boosting에서는 각 단계에서 새롭게 학습되는 트리가 이전 단계에서 계산된 예측값을 기반으로 학습함.
이전 모델이 훈련 데이터의 정답을 참조하여 예측값을 생성하기 때문에, 테스트 시에는 분포가 달라지는 문제가 발생함.

ht=arg⁡min⁡h∈H∑k=1n(−gt(xk,yk)−h(xk))2h_t = \arg \min_{h \in H} \sum_{k=1}^{n} \left( -g_t(x_k, y_k) - h(x_k) \right)^2
  • 모델이 훈련 데이터에 대한 정보를 학습하는 과정에서 자신의 정답을 포함한 예측값을 생성하므로, 테스트 데이터에서는 다르게 동작하게 됨.

CatBoost의 해결책: Ordered Boosting

CatBoost는 Ordered Boosting 기법을 사용하여 Prediction Shift 문제를 해결함.

  • 훈련 데이터를 랜덤한 순서로 정렬하고, 부스팅 모델을 학습할 때 현재 샘플을 포함하지 않은 모델로 예측함.
  • 즉, jj번째 샘플의 예측을 할 때 자신을 포함하지 않은 모델 Mj−1M_{j-1}을 사용하여 훈련함.

이 방법을 통해 부스팅 과정에서 자신이 훈련에 포함된 데이터라는 정보가 잔차 계산에 반영되지 않도록 설계됨.


4. CatBoost vs. XGBoost vs. LightGBM 비교

데이터셋CatBoost (Logloss)LightGBM 증가율XGBoost 증가율
Adult0.2695+2.4%+2.2%
Amazon0.1394+17%+17%
Click0.3917+1.2%+1.2%

범주형 변수가 많은 데이터셋에서 차이가 더 크게 나타남.


5. 결론 및 활용 팁

  • 범주형 변수가 많을 때 → 자동 처리 기능으로 효율적 변환 가능
  • 타깃 누출이 걱정될 때 → Ordered TS로 해결 가능
  • 일반화 성능이 중요한 경우 → Ordered Boosting으로 예측 분포 안정화 가능
  • 하이퍼파라미터 튜닝 없이 빠르게 적용하고 싶을 때 → 기본값이 강력함

CatBoost는 범주형 데이터를 다룰 때 강력한 성능을 발휘하는 Gradient Boosting 모델임.
Ordered TS 및 Ordered Boosting 기법을 통해 기존 Gradient Boosting 모델들의 한계를 극복하며, 다양한 머신러닝 문제에서 활용 가능함.


코드 예시: CatBoost와 Optuna를 활용한 하이퍼파라미터 최적화

1. 데이터 생성 및 전처리

import numpy as np
import pandas as pd
from catboost import CatBoostRegressor, Pool
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import optuna
  • numpy와 pandas를 사용하여 데이터 생성 및 처리
  • catboost에서 CatBoostRegressor, Pool을 가져와 모델 학습
  • sklearn의 train_test_split, mean_squared_error를 사용하여 데이터 분할 및 성능 평가
  • optuna를 활용하여 하이퍼파라미터 최적화
def generate_data(n_samples=1000, n_features=10, random_state=42):
    np.random.seed(random_state)
    X = np.random.randn(n_samples, n_features)  # 정규 분포를 따르는 랜덤 데이터 생성
    y = X @ np.random.randn(n_features) + np.random.randn(n_samples)  # 선형 관계에 노이즈 추가
    return pd.DataFrame(X, columns=[f'feature_{i}' for i in range(n_features)]), y
  • n_samples 개의 샘플과 n_features 개의 특성을 가진 데이터 생성
  • 각 특성은 평균 0, 표준편차 1인 정규 분포를 따르는 랜덤 값
  • y = X @ w + noise 형태로 선형 관계를 갖는 데이터 생성
  • 데이터프레임 형태로 반환
X, y = generate_data()
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42)
  • 생성한 데이터를 train_test_split을 사용하여 80:20 비율로 훈련 데이터와 검증 데이터로 분리
train_pool = Pool(X_train, y_train)
valid_pool = Pool(X_valid, y_valid)
  • Pool 객체 생성 (CatBoost에서 내부적으로 최적화된 데이터 구조)
  • CatBoost의 fit()을 사용할 때 Pool 객체를 사용하면 성능이 향상될 수 있음

2. Optuna를 활용한 하이퍼파라미터 최적화

def objective(trial):
    params = {
        'iterations': trial.suggest_int('iterations', 100, 1000),
        'depth': trial.suggest_int('depth', 4, 10),
        'learning_rate': trial.suggest_loguniform('learning_rate', 0.01, 0.3),
        'l2_leaf_reg': trial.suggest_loguniform('l2_leaf_reg', 1e-1, 10.0),
        'bagging_temperature': trial.suggest_uniform('bagging_temperature', 0.0, 1.0),
        'random_strength': trial.suggest_uniform('random_strength', 0.0, 2.0),
        'border_count': trial.suggest_int('border_count', 32, 255),
        'boosting_type': trial.suggest_categorical('boosting_type', ['Ordered', 'Plain']),
        'verbose': 0
    }
  • trial.suggest_*()을 활용하여 하이퍼파라미터 탐색 범위 지정
  • iterations: 부스팅 반복 횟수 (100~1000)
  • depth: 트리 깊이 (4~10)
  • learning_rate: 학습률 (0.01~0.3, 로그 스케일)
  • l2_leaf_reg: L2 정규화 계수 (0.1~10)
  • bagging_temperature: 배깅 샘플링 비율 조정 (0~1)
  • random_strength: 분할 시 무작위성 추가 (0~2)
  • border_count: 연속형 변수를 이진화할 때 사용할 경계 개수 (32~255)
  • boosting_type: Ordered(순서 기반) 또는 Plain(일반) 부스팅 설정
    model = CatBoostRegressor(**params, random_seed=42)
    model.fit(train_pool, eval_set=valid_pool, early_stopping_rounds=50, verbose=False)
  • CatBoost 모델 생성 및 학습
  • early_stopping_rounds=50을 사용하여 50번 동안 개선이 없으면 학습 조기 종료
    y_pred = model.predict(X_valid)
    mse = mean_squared_error(y_valid, y_pred)
    return mse
  • 검증 데이터에 대한 예측값을 생성한 후 MSE(평균 제곱 오차) 계산
  • 최적화 목표가 mse를 최소화하는 것이므로, MSE 값을 반환

3. Optuna 실행 및 최적 하이퍼파라미터 탐색

study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=50)
  • optuna.create_study()를 통해 MSE를 최소화하는 방향으로 탐색 설정
  • study.optimize()를 호출하여 50번의 실험을 통해 최적의 하이퍼파라미터 찾기
print('Best Parameters found', study.best_params)
  • 최적의 하이퍼파라미터 출력

4. 최적 하이퍼파라미터로 최종 모델 학습 및 평가

best_params = study.best_params
final_model = CatBoostRegressor(**best_params, random_seed=42)
final_model.fit(train_pool, eval_set=valid_pool, early_stopping_rounds=50, verbose=False)
  • Optuna를 통해 찾은 최적의 하이퍼파라미터로 CatBoost 모델을 다시 학습
final_predictions = final_model.predict(X_valid)
final_mse = mean_squared_error(y_valid, final_predictions)
print(f'Final MSE: {final_mse:.5f}')
  • 최적 모델을 사용하여 검증 데이터 예측 후 MSE 계산 및 출력

5. LightGBM 및 XGBoost와 비교 실험

from lightgbm import LGBMRegressor
from xgboost import XGBRegressor
  • LightGBM, XGBoost 모델을 추가로 사용하여 비교
def objective(trial):
    model_type = trial.suggest_categorical('model', ['CatBoost', 'LightGBM', 'XGBoost'])
  • model_type을 CatBoost, LightGBM, XGBoost 중에서 선택하도록 설정
    if model_type == 'CatBoost':
        model = CatBoostRegressor(**params, random_seed=42)
    elif model_type == 'LightGBM':
        model = LGBMRegressor(**params, random_state=42)
    else:
        model = XGBRegressor(**params, random_state=42)
  • 선택된 모델에 맞게 하이퍼파라미터를 적용하여 학습
    model.fit(X_train, y_train, eval_set=[(X_valid, y_valid)], verbose=False)
    y_pred = model.predict(X_valid)
    mse = mean_squared_error(y_valid, y_pred)
    return mse
  • 모델을 훈련하고 검증 데이터에 대한 MSE를 반환
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=50)
  • Optuna를 통해 50번 실험하여 최적 모델 및 하이퍼파라미터 탐색
best_model_type = study.best_params.pop('model')
  • 최적 모델을 저장
if best_model_type == 'CatBoost':
    final_model = CatBoostRegressor(**best_params, random_seed=42)
elif best_model_type == 'LightGBM':
    final_model = LGBMRegressor(**best_params, random_state=42)
else:
    final_model = XGBRegressor(**best_params, random_state=42)
  • 최적의 모델을 선택하여 최종 학습
final_predictions = final_model.predict(X_valid)
final_mse = mean_squared_error(y_valid, final_predictions)
print(f'Final MSE : {final_mse:.5f}')
  • 최적 모델을 평가하고 최종 MSE를 출력

결론

  • CatBoost, LightGBM, XGBoost를 비교하여 최적 모델을 찾고, 하이퍼파라미터 최적화를 수행함
  • Optuna를 활용하여 자동으로 최적의 파라미터를 탐색하고 성능을 향상시킴
  • CatBoost는 범주형 변수를 자동 처리하며 강력한 성능을 보이는 모델임
  • LightGBM, XGBoost와 함께 비교 실험을 통해 모델 선택 가능
profile
gpt로 다시 배우는 개발

0개의 댓글