xgboost自定义目标函数和评估函数


前言:在有些比赛中,需要根据自己的需求来自定义目标函数和评估函数,就自己而言,目标函数需要自定义的场景不太多。为了充分发挥xgboost的框架作用,很多时候自定义评估函数的需求相对强烈。在之前的博文中提到复现Eve的时候,那篇文章主要是基于Keras,自定义了Optimizer,称为Eve。对于主流框架,模块即插即拔,因此我们需要插拔的手艺。文章主要从DMLC的demo出发,针对二分类问题,推导对数似然损失函数的导数,自定义评估函数。

二分类问题的对数似然损失函数如下:

J(θ)=1mi=1m[y(i)loghθ(xx(i))+(1y(i))log(1hθ(x(i)))]J(θ)=−1m∑i=1m[y(i)loghθ(xx(i))+(1−y(i))log(1−hθ(x(i)))]

一阶导数为:

J(θ)=1mi=1m[y(i)hθ(x(i))]J′(θ)=−1m∑i=1m[y(i)−hθ(x(i))]

二阶导数为:

J(θ)=1mi=1mhθ(x(i))[1hθ(x(i))]J″(θ)=−1m∑i=1mhθ(x(i))[1−hθ(x(i))]

下面是DMLC中给出的一个DEMO:

 #!/usr/bin/python
 import numpy as np
 import xgboost as xgb
 ###
 # advanced: customized loss function
 #
 print ('start running example to used customized objective function')
  
 dtrain = xgb.DMatrix('agaricus.txt.train')
 dtest = xgb.DMatrix('agaricus.txt.test')
  
 # note: for customized objective function, we leave objective as default
 # note: what we are getting is margin value in prediction
 # you must know what you are doing
 param = {'max_depth': 2, 'eta': 1, 'silent': 1}
 watchlist = [(dtest, 'eval'), (dtrain, 'train')]
 num_round = 2
  
 # user define objective function, given prediction, return gradient and second order gradient
 # this is log likelihood loss
 def logregobj(preds, dtrain):
 labels = dtrain.get_label()
 preds = 1.0 / (1.0 + np.exp(-preds))
 grad = preds - labels
 hess = preds * (1.0-preds)
 return grad, hess
  
 # user defined evaluation function, return a pair metric_name, result
 # NOTE: when you do customized loss function, the default prediction value is margin
 # this may make builtin evaluation metric not function properly
 # for example, we are doing logistic loss, the prediction is score before logistic transformation
 # the builtin evaluation error assumes input is after logistic transformation
 # Take this in mind when you use the customization, and maybe you need write customized evaluation function
  
 def evalerror(preds, dtrain):
 labels = dtrain.get_label()
 # return a pair metric_name, result
 # since preds are margin(before logistic transformation, cutoff at 0)
 return 'error', float(sum(labels != (preds > 0.0))) / len(labels)
  
 # training with customized objective, we can also do step by step training
 # simply look at xgboost.py's implementation of train
 bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
view raw custom_objective.py hosted with ❤ by  GitHub

xgboost.train中有两个重要参数: obj和feval。其中obj是目标函数,feval是评估函数。目标函数是模型优化的目标,直接用来衡量预测值和真实值之间的差距,常见的例如对数似然损失函数,均方差函数等。评估函数是对预测结果的评估,例如 R2-score等。

读上述代码,自定义了对数似然损失函数,在文档中说,自定义的函数通常要定义目标函数的一阶和二阶导数,但是二阶导数可以不定义。XGBOOST在实现的时候用到了目标函数的二阶导数信息,不同于其他的GBDT实现,只用一阶导数信息。在函数定义中,代码给定了grad和hess。上述结果是化简后的定义,没有化简的定义如下(代码来自参考1):

 def custom_loss(y_pre,D_label): #别人的自定义损失函数
 label=D_label.get_label()
 penalty=2.0
 grad=-label/y_pre+penalty*(1-label)/(1-y_pre) #梯度
 hess=label/(y_pre**2)+penalty*(1-label)/(1-y_pre)**2 #2阶导
 return grad,hess
view raw custom_loss.py hosted with ❤ by  GitHub

feval的定义是应该预测为正的样本中预测错误的样本占总样本数目的比例。从直觉上来说,feval的定义是根据我们对预测结果的关注点来决定的。

通常的时候,可以把目标函数做为评估函数,比如RMSE。在有些数据挖掘比赛中,对于存在一阶导数和二阶导数的评估函数,看到过有些同学直接将评估函数作为目标函数。

下面是feval的f1_score定义,在二分类模型的预测评估中,当召回率(原来样本)和精确率(预测样本)发生冲突时有效评估模型质量的方式:

 def f1_error(preds,dtrain):
 label=dtrain.get_label()
 preds = 1.0/(1.0+np.exp(-preds))
 pred = [int(i >= 0.5) for i in preds]
 tp = sum([int(i == 1 and j == 1) for i,j in zip(pred,label)])
 precision=float(tp)/sum(pred)
 recall=float(tp)/sum(label)
 return 'f1-score',2 * ( precision*recall/(precision+recall) )
view raw custom_f1_error.py hosted with ❤ by  GitHub

总结: 自定义是框架使用的高级技能,为了实现同样的目标,自定义不是必要的。但是通过自定义,可以用更少的代码更好的发挥框架的功能,比如,在每轮训练后打印评估函数的值。类似的事情如GridSearch实现网格搜索,并行调参。当然可以自己写cross-validation和并行处理,但是基于框架所提供的API,可以享受到诸多方便。

参考:

1.携程比赛-客户流失率预测

比赛中的评估函数相对特别,作者写了自己的feval。在文章中给了一个自定义obj,是对数似然损失没有化简的情形。

2.XGBoost官方文档中的一个例子

3.Higgs Boson Machine Learning Challenge中陈天奇的讨论

<think>好的,我现在需要回答用户关于CatBoost默认目标函数自定义方法的问题。首先,我需要回忆一下CatBoost的相关知识,确保信息的准确性。根据用户提供的引用内容,CatBoost在分类回归任务中有不同的默认损失函数。例如,分类问题可能使用LogLoss,而回归问题可能使用RMSE、MAE等。 接下来,我需要确认这些默认函数的具体名称适用场景。比如,二分类的默认目标函数确实是LogLoss,多分类是MultiClass,回归是RMSE或MAE。然后,关于自定义目标函数,用户提到了资料较少,但引用中提到了需要实现目标函数的一阶导数二阶导数,可能还需要Hessian矩阵,这取决于任务类型。 我需要分步骤解释默认目标函数,然后详细说明自定义的步骤,包括定义函数、导数计算、参数设置等。同时,要给出代码示例,这样用户更容易理解。例如,展示如何为回归问题自定义Huber损失函数,并集成到CatBoost中。 还要注意用户提到的引用内容,确保在回答中正确引用。例如,在讨论自定义损失函数时,引用[1][2]中的相关内容需要标注出来。同时,按照用户的要求,生成相关问题,如默认函数的选择、自定义注意事项、与XGBoost/LightGBM的区别等。 最后,检查回答是否符合格式要求:使用中文,数学公式正确用$...$$$...$$,代码块使用正确语法,引用标识正确放置。确保回答结构清晰,步骤明确,帮助用户真正解决问题。</think>### CatBoost默认目标函数自定义方法 #### 一、CatBoost默认目标函数 1. **分类任务** - **二分类**:默认使用对数损失函数(Log Loss),数学表达式为: $$L = -\frac{1}{N} \sum_{i=1}^N \left[ y_i \log(p_i) + (1-y_i) \log(1-p_i) \right]$$ 其中$y_i$为真实标签,$p_i$为预测概率[^1]。 - **多分类**:默认使用多分类对数损失(MultiClass),适用于类别数$K \geq 3$的情况。 2. **回归任务** - 默认目标函数包括均方误差(RMSE)、平均绝对误差(MAE)等。例如RMSE的表达式为: $$L = \sqrt{\frac{1}{N} \sum_{i=1}^N (y_i - \hat{y}_i)^2}$$ 其他支持的回归目标函数如分位数损失(Quantile)、泊松损失(Poisson)等[^2]。 --- #### 二、自定义目标函数方法 CatBoost支持通过自定义损失函数适应特定任务需求,步骤如下: 1. **定义目标函数及其导数** 需提供目标函数的一阶梯度(一阶导数)二阶海森矩阵(二阶导数)。以回归任务为例,若自定义Huber损失函数: ```python def huber_loss(y_true, y_pred, delta=1.0): error = y_pred - y_true condition = np.abs(error) < delta loss = np.where(condition, 0.5 * error**2, delta * (np.abs(error) - 0.5 * delta)) return loss def huber_gradient(y_true, y_pred, delta=1.0): error = y_pred - y_true return np.where(np.abs(error) < delta, error, delta * np.sign(error)) def huber_hessian(y_true, y_pred, delta=1.0): return np.ones_like(y_true) # 海森矩阵简化处理 ``` 2. **封装为CatBoost可调用对象** 使用`CatBoost`的`UserDefinedObjective`类: ```python from catboost import CatBoostRegressor, UserDefinedObjective custom_loss = UserDefinedObjective( eval_metric=huber_loss, gradient=huber_gradient, hessian=huber_hessian ) model = CatBoostRegressor(loss_function=custom_loss, iterations=100) ``` 3. **训练与验证** 需注意自定义函数的数值稳定性,建议对输入数据做标准化处理。 --- #### 三、注意事项 1. **分类任务**:自定义分类损失需额外处理概率输出(如Sigmoid变换)。 2. **评估指标**:自定义目标函数评估指标可独立设置,例如训练用Huber损失,但评估用RMSE。 3. **性能优化**:复杂的自定义函数可能影响训练速度,需权衡精度与效率。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值