XGBoost における単調性制約
XGBoost の単調性制約
XGBoost などの Tree 系アルゴリズムは表現力が大きいため、容易に bias を小さくできます。
下の例では、増加するトレンドにある特徴量と目的変数がにノイズが乗ったデータに対して XGBoost でフィッティングすると、全体的には上昇トレンドを捉えますが、局所的に振動してしまいます。
これは、XGBoost が表現力(データにフィットする能力)が高いゆえにできることなのですが、一方で過度にデータにフィットしているとも言えます。
もちろん、それはモデル自身が判断することではなく、課題設定や事前情報、ビジネス上の考慮などで決まる場合が多いです。
ただ、諸理由によりこの「増加するトレンド」であったり「減少するトレンド」を制約として加え、制約の中で最大限にフィッティングさせたい場合に、この単調性の制約(単調に増加(減少)する制約)は有効です。
一般的に、このような制約を加える理由としては「精度向上のために」というよりも「解釈しやすくするため」という動機が多いように思います。
下図が単調性制約を与えてフィッティングしたモデルの結果です。 これを見ると、大局的な傾向は捉えていながら、局所的に増減する振動が消えています。
というようなことが下のページに書いてあるのですが、簡単に内容と実際のコードを書いておきます。
例では次のデータを用いています(上図2つも同様です)
]
# jupyter notebook での実行 import numpy as np import xgboost as xgb import matplotlib.pylab as plt from sklearn.cross_validation import train_test_split %matplotlib inline # データの作成 N = 1000 x1 = np.random.random(N) x2 = np.random.random(N) y = (5 * x1 + np.sin(10 * np.pi * x1)) - (5 * x2 + np.cos(10 * np.pi * x2)) + np.random.normal(0.0, 0.01) # x1 の分布(単調増加) plt.plot(x1, y, 'o', alpha=0.5) # x2 の分布(単調減少) plt.plot(x2, y, 'o', alpha=0.5) # 学習データ X = np.array([x1, x2]).T X_train, X_test, y_train, y_test = train_test_split(X, y) # 描画用 # 片方の変数を描画するときはもう片方を 0.5 で固定(影響を最小限にするため) def plot_response_x1(model): # x1 (単調増加変数のレスポンス) _x1 = np.linspace(0, 1, 100) _x2 = np.zeros(100) + 0.5 _X = np.array([_x1, _x2]).T _y = model.predict(_X) plt.plot(X_test[:,0], y_test, 'o', alpha=0.5) plt.plot(_x1, _y, color = 'black') def plot_response_x2(model): # x2 (単調減少変数のレスポンス) _x1 = np.zeros(100) + 0.5 _x2 = np.linspace(0, 1, 100) _X = np.array([_x1, _x2]).T _y = model.predict(_X) plt.plot(X_test[:, 1], y_test, 'o', alpha=0.5) plt.plot(_x2, _y, color = 'black') # 単調性制約のない XGBoost で回帰モデルを構築します. model = xgb.XGBRegressor() model.fit(X_train, y_train) plot_response_x1(model) plot_response_x2(model) # 単調性制約を課した XGBoost で回帰モデルを構築します. model = xgb.XGBRegressor(monotone_constraints=(1,-1)) model.fit(X_train, y_train) plot_response_x1(model) plot_response_x2(model)
パラメータについて
monotone_constraints
1:単調増加制約、0:制約を加えない(デフォルト)、-1:単調減少制約、で説明変数毎にリストで設定します。例えば
- (1, 0): 1つ目の説明変数に単調増加制約を与え、2つ目の説明変数には制約を与えない
- (0,-1): 1つ目の説明変数に単調増加制約を与えず、2つ目の説明変数には単調減少制約を与える
となります。
tree_method
monotone_constraints を利用する場合は tree_method として次のうちのどれかを指定する必要があります。
- tree_method='exact','hist', gpu_hist