提问人:anat 提问时间:10/26/2023 更新时间:11/14/2023 访问量:93
LGBMRegressor python 中 tweedie/Regression_l1 目标的自定义损失函数
Custom loss function of tweedie/Regression_l1 objective in LGBMRegressor python
问:
我正在使用带有 objective=“tweedie”/objective='Regression_l1' 的 LGBMRegressor 模型,我需要创建一个自定义损失函数,该函数采用原始目标并根据业务需求对其进行一些更改。 在我开始更改之前,我正在尝试实现完全是 tweedie/Regression_l1 的自定义损失函数,以确保它是相同的。 我尝试了一些 tweedie 的常规实现,得到了不同的结果。 有人可以帮忙吗?
答:
查看LightGBM#RegressionTweedieLoss
()的C++实现,您可以尝试看看是否可以在Python中模拟相同的实现,并查看结果是否不同(在根据业务需求应用更改之前)
像这样的东西(Python 中的松散翻译):
import lightgbm as lgb
import numpy as np
class CustomTweedieLoss:
def __init__(self, rho=1.5):
self.rho = rho
def __call__(self, preds, train_data):
labels = train_data.get_label()
exp_1_score = np.exp((1 - self.rho) * preds)
exp_2_score = np.exp((2 - self.rho) * preds)
grad = -labels * exp_1_score + exp_2_score
hess = -labels * (1 - self.rho) * exp_1_score + (2 - self.rho) * exp_2_score
return grad, hess
# Usage:
objective = CustomTweedieLoss(rho=1.5)
LightGBM#RegressionL1loss()
的想法相同:
import numpy as np
import lightgbm as lgb
class CustomL1Loss:
def __init__(self, weights=None):
self.weights = weights
def __call__(self, preds, train_data):
labels = train_data.get_label()
diff = preds - labels
grad = np.sign(diff)
hess = np.ones_like(preds)
if self.weights is not None:
grad *= self.weights
hess *= self.weights
return grad, hess
# Usage:
# Get the weights data, if any, then:
# objective = CustomL1Loss(weights=weights_data)
评论
您似乎正在使用 objective=“tweedie” 或 objective='Regression_l1' 设置来使用 LGBMRegressor 模型,并尝试创建与这些目标的行为完全匹配的自定义损失函数。但是,在实现自定义损失函数时,您遇到了一些差异。
要创建模拟内置目标行为的自定义损失函数,请务必严格遵循目标函数的数学公式。对于 Tweedie 目标,LGBMRegressor 文档指定该目标是 Tweedie 偏差:
obj = tweedie(y, y_hat) = -2 * sum(w * (y * phi - (y_hat * phi)**(2/p) / (2/p)) / (1/p - 1))
其中 y 是真实目标值,y_hat 是预测值,w 是样本的权重,phi 是色散参数,p 是功效参数。
对于回归 L1 目标,目标是平均绝对误差:
obj = |y - y_hat|
如果您观察到结果的差异,则自定义损失函数的实现可能存在差异。确保自定义损失函数遵循 Tweedie 偏差或平均绝对误差的精确数学公式,具体取决于您要复制的目标。
下面是 Tweedie 的自定义损失函数示例:
import numpy as np
def custom_tweedie(y_true, y_pred, phi, p):
dev = -2 * np.sum(y_true * phi - (y_pred * phi)**(2/p) / (2/p))
return dev
# Usage:
# loss = custom_tweedie(y_true, y_pred, phi, p)
对于回归 L1,您可以使用平均绝对误差:
def custom_regression_l1(y_true, y_pred):
return np.mean(np.abs(y_true - y_pred))
# Usage:
# loss = custom_regression_l1(y_true, y_pred)
确保参数(Tweedie 的 phi 和 p)设置正确,并与你在 LGBMRegressor 中使用的配置匹配。
评论