首页 > 解决方案 > 如何在 Brier 分数上优化提升树以进行分类?

问题描述

我有一个二进制分类任务并使用 xgboost 包来解决它。基本上,我只是使用增强树来做到这一点。但是我正在接受 Brier 分数的评估,所以我想我会优化 Brier 损失函数(定义为应用于逻辑分类之上的 brier 分数),这导致我定义了 Brier 损失的梯度和粗麻布,如下所示:

def brier(preds, dtrain):
   labels = dtrain.get_label()
   preds = 1.0 / (1.0 + np.exp(-preds))
   grad = 2*(preds-labels)*preds*(1-preds)
   hess = 2*(2*(labels+1)*preds-labels-3*preds*preds)*preds*(1-preds)
   return grad, hess

def evalerror(preds, dtrain):
   preds = 1.0 / (1.0 + np.exp(-preds))
   labels = dtrain.get_label()
   errors = (labels - preds)**2
   return 'brier-error', float(np.sum(errors)) / len(labels)

param = {'eta':0.01,
'max_depth': 6,  # the maximum depth of each tree
#'objective': 'binary:logistic',
'booster' : 'gbtree',
'eval_metric':['rmse', 'auc']}

bst = xgb.train(param,dtrain, num_boost_round=999,early_stopping_rounds=10,obj=brier, feval=evalerror,evals=[(dtrain,'train'),(dtest,'test')])

唯一的问题是,通过这样做,我在测试集上的预测得到了负值,这表明 xgboost 模型的输出不是预期的逻辑概率。有谁知道我在这里缺少什么,或者是否有更好的方法来优化 brier 分数?

任何帮助将非常感激!!

谢谢,

标签: pythonmachine-learningxgboost

解决方案


我遇到了同样的问题并进行了一些调查。我认为 OP 的计算是正确的,这里的问题不是使用对角近似而不是 @Damodar8 建议的精确粗麻布,因为它指的是多类分类问题。

正如这里指出的:

注意:当你做自定义损失函数时,默认的预测值为margin。这可能会使内置评估指标无法正常运行例如,我们正在做逻辑损失,预测是逻辑转换之前的分数内置评估错误假设输入是在逻辑转换之后 使用自定义时请记住这一点,也许您需要编写自定义评价函数

尽管评论本身很难解开,但粗体字解释了 OP 的问题。解决方案是仅对结果使用逻辑转换bst.predict。完整示例如下:

import numpy as np
import xgboost as xgb

dtrain = xgb.DMatrix('/home/kuba/Desktop/agaricus.txt.train')
dtest = xgb.DMatrix('/home/kuba/Desktop/agaricus.txt.test')

def brier(preds, dtrain):
    labels = dtrain.get_label()
    preds = 1.0 / (1.0 + np.exp(-preds))
    grad = 2*(preds-labels)*preds*(1-preds)
    hess = 2*(2*(labels+1)*preds-labels-3*preds*preds)*preds*(1-preds)
    return grad, hess

def evalerror(preds, dtrain):
    preds = 1.0 / (1.0 + np.exp(-preds))
    labels = dtrain.get_label()
    errors = (labels - preds)**2
    return 'brier-error', float(np.sum(errors)) / len(labels)

param = {'max_depth': 2, 'eta': 1, 'silent': 1}
watchlist = [(dtest, 'eval'), (dtrain, 'train')]
num_round = 2

bst = xgb.train(param, dtrain, num_round, watchlist, obj=brier, feval=evalerror)

pred = bst.predict(dtest)
pred.min(), pred.max()
# (-5.809054, 2.2280416)

prob = 1 / (1 + np.exp(-pred))
prob.min(), prob.max()
# (0.0029912924, 0.9027395)

推荐阅读