ゆるふわめも

東京か京都にいます。

エラー解決:PythonのXGBoostで目的関数を変更する

これまでの場合

過去のバージョン(以下)では確か custom_objective パラメータにてgradientとhessian matrixを返すような関数を渡せばよかった。

paper.hatenadiary.jp

xgboost-0.4a30では objective がこれに該当する。が…custom objectiveで検索してもkaggleの優勝者のブログしか出てこない。

エラー内容

コード

def logregobj(dtrain, preds):
    grad = preds
    hess = preds * (1.0-preds)
    return grad, hess

model = XGBRegressor(objective=xgb_quantile_obj)
model.fit(X_train, y_train)

エラーメッセージ

XGBoostError: b'unknown objective function type: <function logregobj at 0x11608c9d8>'

解決

解決法:xgboost-0.6a2にアップデートする。

ドキュメントより引用すると

Note: A custom objective function can be provided for the objective parameter. In this case, it should have the signature objective(y_true, y_pred) -> grad, hess:

y_true: array_like of shape [n_samples] The target values

y_pred: array_like of shape [n_samples] The predicted values grad: array_like of shape [n_samples] The value of the gradient for each sample point.

hess: array_like of shape [n_samples] The value of the second derivative for each sample point

引用元:

Python API Reference — xgboost 0.6 documentation

正しいように思う…と思ってバージョンを xgboost-0.6a2 にアップデートしたらエラーがなくなりました。ただのバグだったようです。ただ、確か何か理由があって xgboost-0.4a30にしていたはずなのでまたどこかでつまづくかもしれません。

実装例・参考

openになっているので実装してコミットしたほうがいいかもしれない。あと problems with custom objective function for mean absolute percentage error(MAPE) · Issue #1818 · dmlc/xgboost · GitHub

def mspe(y, dtrain):
    yhat = dtrain.get_label()
    grad = 2.0/yhat * (y * 1.0 / yhat - 1)
    hess = 2.0/(yhat**2)
    return grad, hess

grad-1 をかける必要があると思った。