catBoostの概要と使い方

CatBoostについて(ざっくり)

  • 勾配ブースティング決定木 (Gradient Boosting Decision Tree) を扱うためのフレームワーク
  • LightGBM や XGBoost と並んでよく用いられている。予測精度や速度が量さやに比べて優れているかは実際よく分からない(参考 CatBoost解説 -pythonでLightGBM,XGBoostと性能比較-)

技術的な内容の詳細はcatboostの推論の仕組みを理解する (1/2)を参照。

勾配ブースティングとは

  • ブースティング :今までに学習したモデルの情報を使って、新たのモデルを構築することでデータの学習を進める方法
    (クラス分類で誤分類されたサンプルや、回帰モデルで誤差の大きかったサンプルを改善するように新たなモデルが構築される)
  • 勾配:ブースティングにおいて、前回の学習したモデルの目的関数(損失関数)の勾配(Gradient)を用いて新たなモデルを構築する。

catboostのハイパーパラメータについて

XGBoost, lightGBMに比べて情報が極端に少ないので、この記事での説明は割愛。

以下の記事参照

例えば、パラメータ探索空間は以下のようになる。(optunaを使用する場合)

params = { 'depth' : trial.suggest_int('depth', 4, 15),
            'random_strength' :trial.suggest_loguniform('random_strength', 1e-9, 100),       
            'l2_leaf_reg': trial.suggest_int('l2_leaf_reg', 2, 30),                
            'bagging_temperature' :trial.suggest_loguniform('bagging_temperature', 0.01, 100.00), 
            # 'od_type': trial.suggest_categorical('od_type', ['IncToDec', 'Iter']),
            # 'od_pval' :trial.suggest_int('od_pval', 10, 50),
            # 'od_wait' :trial.suggest_int('od_wait', 10, 50),
            'learning_rate' : trial.suggest_loguniform('learning_rate', 0.01, 1.0),  
            'border_count' : trial.suggest_int('border_count',1,255)
            }

コード

XGBoost, lightGBMと同じく、通常の方法とscikit-learnのラッパー?を使用する方法がある。

準備

CatBoostのインストール

pip install catboost scikit-learn

データの準備

scikit-learnのボストンの住宅価格データを使用する

import numpy as np
import pandas as pd

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

import catboost as cb
from catboost import CatBoost
from catboost import Pool

boston = load_boston()

df_X = pd.DataFrame(boston.data, columns=boston.feature_names)
df_y = pd.DataFrame(boston.target,columns=['Price'])

X_train, X_test, y_train, y_test = train_test_split(df_X, df_y,test_size=0.3)

通常の方法

# データセットを生成する
train_pool = Pool(X_train, y_train)
test_pool = Pool(X_test, y_test)

# LightGBMのハイパーパラメータを設定する
params = {'loss_function': 'RMSE',
         'num_boost_round': 100,}

# 上記のパラメータでモデルを学習する
model = CatBoost(params)
model.fit(train_pool)

y_pred = model.predict(X_test)

# RMSE を計算する
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print('RMSE:',round(rmse,3))
"""output
RMSE: 2.947
"""

# 特徴量の重要度を取得する
feature_importance = model.get_feature_importance()
print(feature_importance)
"""output
[ 4.31040001  0.67741023  2.2140446   1.14988867  4.04409144 32.42709848
  4.48011999  6.86468575  1.45404807  3.65956433  6.64365716  3.74959832
 28.32539295]
"""

scikit-learn インターフェースを使用する方法

model = cb.CatBoostRegressor(num_boost_round=1000,
                            loss_function='RMSE'
                            )

#分類問題の場合は下記を使う
# cb.CatBoostClassifier()

model.fit(X_train, y_train, eval_set=[(X_test, y_test)])

y_pred = model.predict(X_test)

# RMSE を計算する
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print('RMSE:',round(rmse,3))
"""output
RMSE: 2.922
"""

# 特徴量の重要度を取得する
feature_importance = model.get_feature_importance()
print(feature_importance)
"""output
[ 5.35344119  0.6049604   1.26280272  1.97634138  4.52207232 34.79837069
  3.16250746  8.31176284  1.9124929   3.11624666  5.08906134  2.7184551
 27.171485  ]
"""

最適なブーストラウンド数を自動で決める方法

 ブーストラウンド数は少なすぎると過小適合、多すぎると学習データに過剰適合してしまう恐れがあるため、適切な値を設定する必要がある。
 early_stopping_rouds オプションを使うと訓練データとともに精度評価用データをモデルに渡ことで、モデルの性能が頭打ちになったところで学習を打ち切ることができ、最適なブーストラウンド数を決めることができる。
 評価用データはeval_setオプションで渡す。またこの際に精度評価に用いる指標も指定する必要がある。

  • n_estimators:最大のブーストラウンド数(何回学習するか)
  • early_stopping_rounds:何ラウンド進めた時に予測性能向上みられなかった時に学習を打ち切る。

通常の方法

train_pool = Pool(X_train, label=y_train)
test_pool = Pool(X_test, label=y_test)

params = {'loss_function': 'RMSE',
        'num_boost_round': 1000,
        'early_stopping_rounds': 10,
        }

model = CatBoost(params)
model.fit(train_pool, eval_set=[test_pool], use_best_model=True)

y_pred = model.predict(test_pool)

# RMSE を計算する
mse = np.sqrt(mean_squared_error(y_test, y_pred))
print('RMSE:',round(rmse,3))
"""output
RMSE: 2.922
"""

scikit-learnインターフェースを使用

# scikit-learn インターフェースを備えたラッパー
model = cb.CatBoostRegressor(num_boost_round=1000,
                        loss_function='RMSE',
                        early_stopping_rounds=10,
                        )

model.fit(X_train, y_train, eval_set=[(X_test, y_test)])

y_pred = model.predict(X_test)

mse = np.sqrt(mean_squared_error(y_test, y_pred))
print('RMSE:',round(rmse,3))
"""output
RMSE: 2.922
"""

参考

関連書籍