我知道xgboost需要第一个渐变和第二个渐变,但是其他任何人都使用过" mae"作为obj函数?
答案 0 :(得分:31)
首先是一点理论,对不起!你要求MAE的毕业和粗麻布,但是,MAE不是continuously twice differentiable所以试图计算一阶和二阶导数变得棘手。下面我们可以看到"扭结"在x=0
,这可以防止MAE连续可分。
此外,二阶导数在表现良好的所有点都为零。在XGBoost中,二阶导数用作叶子权重的分母,当为零时,会产生严重的数学错误。
鉴于这些复杂性,我们最好的办法是尝试使用其他一些表现良好的功能来近似MAE。我们来看看。
我们可以看到上面有几个函数接近绝对值。显然,对于非常小的值,平方误差(MSE)是MAE的相当好的近似值。但是,我认为这对您的用例来说还不够。
Huber 损失是一个记录良好的损失函数。然而,它并不顺利,所以我们不能保证平滑的衍生品。我们可以使用Psuedo-Huber函数来近似它。它可以在python XGBoost中实现,如下所示,
import xgboost as xgb
dtrain = xgb.DMatrix(x_train, label=y_train)
dtest = xgb.DMatrix(x_test, label=y_test)
param = {'max_depth': 5}
num_round = 10
def huber_approx_obj(preds, dtrain):
d = preds - dtrain.get_labels() #remove .get_labels() for sklearn
h = 1 #h is delta in the graphic
scale = 1 + (d / h) ** 2
scale_sqrt = np.sqrt(scale)
grad = d / scale_sqrt
hess = 1 / scale / scale_sqrt
return grad, hess
bst = xgb.train(param, dtrain, num_round, obj=huber_approx_obj)
替换obj=huber_approx_obj
可以使用其他功能。
公平损失根本没有完整记录,但似乎工作得相当好。公平损失函数是:
可以这样实现,
def fair_obj(preds, dtrain):
"""y = c * abs(x) - c**2 * np.log(abs(x)/c + 1)"""
x = preds - dtrain.get_labels()
c = 1
den = abs(x) + c
grad = c*x / den
hess = c*c / den ** 2
return grad, hess
此代码取自Kaggle Allstate Challenge中的第二位solution。
Log-Cosh 损失功能。
def log_cosh_obj(preds, dtrain):
x = preds - dtrain.get_labels()
grad = np.tanh(x)
hess = 1 / np.cosh(x)**2
return grad, hess
最后,您可以使用上述功能作为模板创建自己的自定义丢失函数。
答案 1 :(得分:1)
我正在以〜正态分布的Y来运行Huber / Fair度量标准,但是由于某种原因,alpha <0(并且一直都是Fair),结果预测将等于零...
答案 2 :(得分:0)
对于上述的Huber损失,我认为坡度预先未出现负号。应该为
grad = - d / scale_sqrt