为什么我的自定义 lightgbm 损失没有减少?
Why doesn't my custom lightgbm loss decrease?
我在 lightgbm 中实现了自定义平均误差 (MAE) 损失。梯度不为零,但损失保持不变。怎么可能?
我的实现:
def abs_obj(preds, dtrain):
y_true = dtrain.get_label()
a = preds - y_true
grad = np.sign(a)
hess = np.zeros(len(a))
return grad, hess
def abs_eval(preds, dtrain):
y_true = dtrain.get_label()
loss = np.abs(preds - y_true).sum()
return "error", loss, False
一个最小的可重现示例:损失保持不变。
dtrain = pd.DataFrame({'x':np.random.rand(100),
'y':np.random.rand(100)})
ytrain = dtrain.x + 2 * dtrain.y
dval = dtrain
yval = ytrain
lgb_train = lgb.Dataset(dtrain, ytrain)
lgb_valid = lgb.Dataset(dval, yval)
params = {'objective':None,
'learning_rate':30,
'num_leaves':33}
clf = lgb.train(params,
lgb_train,
valid_sets=[lgb_valid],
num_boost_round=10,
verbose_eval=1,
fobj=abs_obj,
feval=abs_eval)
对于 lightgbm 中的自定义损失,您需要具有正二阶导数的二次微分函数。
为了加快他们的算法,lightgbm 使用 Newton's approximation 找到最佳叶值:
y = - L' / L''
(详见this blogpost)。
当二阶导数为零或函数不可二次微分时,这种近似是非常错误的。 Lightgbm 有内置的 objective 函数不符合这个标准,比如 MAE。对于这些功能,它们有不同的特殊实现。
我在 lightgbm 中实现了自定义平均误差 (MAE) 损失。梯度不为零,但损失保持不变。怎么可能?
我的实现:
def abs_obj(preds, dtrain):
y_true = dtrain.get_label()
a = preds - y_true
grad = np.sign(a)
hess = np.zeros(len(a))
return grad, hess
def abs_eval(preds, dtrain):
y_true = dtrain.get_label()
loss = np.abs(preds - y_true).sum()
return "error", loss, False
一个最小的可重现示例:损失保持不变。
dtrain = pd.DataFrame({'x':np.random.rand(100),
'y':np.random.rand(100)})
ytrain = dtrain.x + 2 * dtrain.y
dval = dtrain
yval = ytrain
lgb_train = lgb.Dataset(dtrain, ytrain)
lgb_valid = lgb.Dataset(dval, yval)
params = {'objective':None,
'learning_rate':30,
'num_leaves':33}
clf = lgb.train(params,
lgb_train,
valid_sets=[lgb_valid],
num_boost_round=10,
verbose_eval=1,
fobj=abs_obj,
feval=abs_eval)
对于 lightgbm 中的自定义损失,您需要具有正二阶导数的二次微分函数。
为了加快他们的算法,lightgbm 使用 Newton's approximation 找到最佳叶值:
y = - L' / L''
(详见this blogpost)。
当二阶导数为零或函数不可二次微分时,这种近似是非常错误的。 Lightgbm 有内置的 objective 函数不符合这个标准,比如 MAE。对于这些功能,它们有不同的特殊实现。