当前位置:   article > 正文

XGBoost_xgboost损失函数

xgboost损失函数

背景

GBDT的基础上,有了XGB。XGB"(eXtreme Gradient Boosting极端梯度提升)本质还是 一个GBDT (Gradien tBoosting Decision Tree),XGB (Xtreme Gradient Boosting) 的本质还是一个GBDT, 但是在速度和效率上都发挥到了极致,XGB和GBDT比较大的不同就是目标函数的定义。

原理

XGB使用泰勒展开来近似目标函数。
二阶泰勒展开公式:
在这里插入图片描述
最小化下列损失函数,
在这里插入图片描述
γ \gamma γ λ \lambda λ是预先设定的超参数, T T T是叶子节点的数量, w w w是叶子结点的权重。
在这里插入图片描述
化简后:
在这里插入图片描述
g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ ( t − 1 ) ) g_{i}=\partial_{\hat{y}^{(t-1)}} l\left(y_{i}, \hat{y}^{(t-1)}\right) gi=y^(t1)l(yi,y^(t1)), 表示损失对 y ^ ( t − 1 ) \hat{y}^{(t-1)} y^(t1)求导。
h i = ∂ y ^ ( t − 1 ) 2 l ( y i , y ^ ( t − 1 ) ) h_{i}=\partial_{\hat{y}(t-1)}^{2} l\left(y_{i}, \hat{y}^{(t-1)}\right) hi=y^(t1)2l(yi,y^(t1)), 表示损失对 y ^ ( t − 1 ) \hat{y}^{(t-1)} y^(t1)求导。
可以得到:
g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ ( t − 1 ) ) = ∂ y ^ ( t − 1 ) ( y i − y ^ ( t − 1 ) ) 2 = − 2 y i + 2 y ^ ( t − 1 ) gi=ˆy(t1)l(yi,ˆy(t1))=ˆy(t1)(yiˆy(t1))2=2yi+2ˆy(t1) gi=y^(t1)l(yi,y^(t1))=y^(t1)(yiy^(t1))2=2yi+2y^(t1)
h i = ∂ y ^ ( t − 1 ) 2 l ( y i , y ^ ( t − 1 ) ) = 2 {h_i} = \partial _{\hat y(t - 1)}^2l\left( {{y_i},{{\hat y}^{(t - 1)}}} \right) = 2 hi=y^(t1)2l(yi,y^(t1))=2
g i g_i gi h i h_i hi的结果带入公式展开,可以得到和原公式展开相同的结果。
为啥公式的第一行的 f t ( x i ) f_t(\bf{x_i}) ft(xi)消失了,因为这个得到的结果也是对应叶子节点的权重。注解:最后一步的转化思路是从在这个树中,每个样本落在哪个节点上转为了每个节点 上有哪些样本。

在这里插入图片描述
这个是对 w j w_j wj做了求导,将最外层的求和符号去掉,然后就可以得到最后的结果。
在这里插入图片描述
这个是将优化后的 w w w带进去,然后得到的结果。
3. XGBoost在什么地方做的剪枝,怎么做的?

(1) 当引入的分割带来的增益小于一个阈值时,我们就可以减掉这个分割(参考决策树的分割)。
在这里插入图片描述

(2)在模型中加入正则

  1. XGBoost特征重要性实现原理:
    每个特征对应一个模型参数 w i w_i wi,这个参数越大说明这个特征越重要。
    gain :该特征在其出现过的所有树中产生的平均增益(我自己的理解就是目标函数减少值总和的平均值,这里也可以使用增益之和)。

每一个特征的分裂都会产生好多树,那么这些树是会带来增益的。

代码训练

#训练集和验证集数据划分
import xgboost as xgb
#train_x是DataFrame数据,选择对应的列就行
nums = int(train_x.shape[0] * 0.80)

# 训练集验证集划分
trn_x, trn_y, val_x, val_y = train_x[:nums], train_y[:nums], train_x[nums:], train_y[nums:]

#训练集
train_matrix = xgb.DMatrix(trn_x, label=trn_y.values, missing=np.nan)
valid_matrix = xgb.DMatrix(val_x, label=val_y.values, missing=np.nan)
# test_matrix = clf.DMatrix(test_x, label=val_y, missing=np.nan)
test_matrix = xgb.DMatrix(test_x, missing=np.nan)

params = {'booster': 'gbtree',
          'eval_metric': 'mae',
          'min_child_weight': 5,
          'max_depth': 8,
          'subsample': 0.5,
          'colsample_bytree': 0.5,
          'eta': 0.0015,
          'seed': 2020,
          'nthread': 4,
          'silent': True,
          }

watchlist = [(train_matrix, 'train'), (valid_matrix, 'eval')]

model = xgb.train(params, train_matrix, num_boost_round=50000, evals=watchlist, verbose_eval=500,
                  early_stopping_rounds=1000)
#划分的验证集数据
val_pred = model.predict(valid_matrix, ntree_limit=model.best_ntree_limit).reshape(-1, 1)
#需要测试的数据
test_pred = model.predict(test_matrix, ntree_limit=model.best_ntree_limit).reshape(-1, 1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

问题

XGBoost为什么要用二阶泰勒展开
  1. 二阶信息本身就能让梯度收敛更快更准确。这一点在优化算法里的牛顿法里已经证实了。可以简单认为一阶导指引梯度方向,二阶导指引梯度方向如何变化。
  2. 不同损失的求导是不一样的,为了可以统一损失函数求导的形式,所以用二阶泰勒展开。

参考资料

https://zhuanlan.zhihu.com/p/290964953?utm_source=ZHShareTargetIDMore (这个博客里面树模型比较详细)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/912115
推荐阅读
相关标签
  

闽ICP备14008679号