项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.CART树回顾

在正式讲Xgboost之前,我们先回顾一下CART树。
CART树的生成过程,就是递归构建二叉树的过程,本质上是在某个特征维度对样本空间进行划分。这种空间划分是一种NP Hard问题,因此一般都是用启发式的方式去求解,即求某个特征j的且分点s,使得
min⁡j,s[min⁡c1∑xi∈R1(j,s)(yi−c1)2+min⁡c2∑xi∈R2(j,s)(yi−c2)2]\min_ { j , s } \left[ \min _ { c _ { 1 } } \sum _ { x _ { i } \in R _ { 1 } ( j , s ) } \left( y _ { i } - c _ { 1 } \right) ^ { 2 } + \min _ { c _ { 2 } } \sum _ { x _ { i } \in R _ { 2 } ( j , s ) } \left( y _ { i } - c _ { 2 } \right) ^ { 2 } \right]j,smin​⎣⎡​c1​min​xi​∈R1​(j,s)∑​(yi​−c1​)2+c2​min​xi​∈R2​(j,s)∑​(yi​−c2​)2⎦⎤​

2.XGBoost叶子节点取值推导

XGBoost的大体思路跟GBDT一样,也是通过不断进行特征分裂添加树,来学习一个新的弱学习器,来拟合上次预测结果的残差。

首先来看一下XGBoost的损失函数
L(ϕ)=∑il(yi,y^i)+∑kΩ(fk),其中Ω(fk)=γT+12λ∣∣w∣∣2L ( \phi ) = \sum _ { i } l \left( y _ { i } , \hat { y } _ { i } \right) + \sum _ { k } \Omega \left( f _ { k } \right) ,\quad 其中 \quad \Omega \left( f _ { k } \right) = \gamma T + \frac { 1 } { 2 } \lambda | | w | | ^ { 2 }L(ϕ)=i∑​l(yi​,y^​i​)+k∑​Ω(fk​),其中Ω(fk​)=γT+21​λ∣∣w∣∣2

很容易可以看出来
∑il(yi,y^i)\sum\limits_i l \left( y _ { i } , \hat { y } _ { i } \right)i∑​l(yi​,y^​i​)是代表预测值与真实值的偏差,而∑kΩ(fk)\sum\limits_k \Omega \left( f _ { k } \right)k∑​Ω(fk​)为正则项。

其中,yiy_iyi​为样本的真实值,y^i\hat y_ iy^​i​为预测值。fkf_kfk​表示第k棵树,γ\gammaγ为叶子树的正则项,起到剪枝的作用,T为树的叶子节点个数,www为叶子节点的分数,λ\lambdaλ为叶子节点分数的正则项,起到防止过拟合的作用。

前面树系列的文章提到过很多次,boost系列算法的核心思想是用新生成的树拟合上次预测的残差(对于GBDT来说是上次预测的负梯度方向)。生成第t棵树后,预测值可以写为
y^i=y^it−1+ft(x)\hat y_i = \hat y_i ^{t-1} + f_t(x)y^​i​=y^​it−1​+ft​(x)

此时,损失函数可以表示为

Lt=∑i=1l(yit,y^it−1)+ft(xi)+Ω(ft)L^t = \sum _{i=1} l ( y _i^t , \hat y_i ^{t-1}) + f_t(x_i) + \Omega (f _t)Lt=i=1∑​l(yit​,y^​it−1​)+ft​(xi​)+Ω(ft​)

于是我们要找一个ftf_tft​让损失函数最小。对上面的式子进行泰勒展开
L(t)≃∑i=1n[l(yi,y^(t−1))+gift(xi)+12hift2(xi)]+Ω(ft)\mathcal { L } ^ { ( t ) } \simeq \sum _ { i = 1 } ^ { n } \left[ l \left( y _ { i } , \hat { y } ^ { ( t - 1 ) } \right) + g _ { i } f _ { t } \left( \mathbf { x } _ { i } \right) + \frac { 1 } { 2 } h _ { i } f _ { t } ^ { 2 } \left( \mathbf { x } _ { i } \right) \right] + \Omega \left( f _ { t } \right)L(t)≃i=1∑n​[l(yi​,y^​(t−1))+gi​ft​(xi​)+21​hi​ft2​(xi​)]+Ω(ft​)

其中,
gi=∂l(yi,y^it−1)∂y^it−1g_i = \frac{\partial l(y_i, \hat y_i ^{t-1})} {\partial \hat y_i ^{t-1}}gi​=∂y^​it−1​∂l(yi​,y^​it−1​)​
hi=∂2l(yi,y^it−1)∂(y^it−1)2h_i = \frac{\partial ^ 2 l(y_i, \hat y_i ^{t-1})} {\partial (\hat y_i ^{t-1})^2}hi​=∂(y^​it−1​)2∂2l(yi​,y^​it−1​)​

其中gi,hig_i, h_igi​,hi​的含义可以按如下方式理解
假设目前已经有t-1棵数,这t-1棵树组成的模型对第i个训练样本有一个预测值y^i\hat y_iy^​i​,y^i\hat y_iy^​i​与真实值yiy_iyi​肯定有差距,这个差距可以用l(yi,y^i)l(y_i, \hat y_i)l(yi​,y^​i​)这个损失函数来衡量,所以此处的gig_igi​与hih_ihi​就是对于该损失函数的一阶导和二阶导。(参考文献1)

搞定了前面的损失函数部分,接下来再观察一下正则项
Ω(ft)=γT+12λ∑j=1Twj2\Omega (f_t) = \gamma T + \frac{1}{2} \lambda \sum_{j=1}^T w_j^2Ω(ft​)=γT+21​λj=1∑T​wj2​

对于上面的正则项,我们最简单的理解方式为:要使模型尽可能简单,那就是叶子节点的个数T要小,同时叶子节点上的值也尽可能小。

因为前t-1棵树的预测分数与y的残差对目标函数优化不影响, 可以直接去掉,所以损失函数可以写成

L(t)≃∑i=1n[gift(xi)+12hift2(xi)]+Ω(ft)\mathcal { L } ^ { ( t ) } \simeq \sum _ { i = 1 } ^ { n } \left[ g _ { i } f _ { t } \left( \mathbf { x } _ { i } \right) + \frac {1} {2} h_i f _ { t } ^ { 2 } \left( \mathbf { x } _ { i } \right) \right] + \Omega \left( f _ { t } \right)L(t)≃i=1∑n​[gi​ft​(xi​)+21​hi​ft2​(xi​)]+Ω(ft​)

上面式子的含义是将每个样本的损失函数相加,而每个样本最终都会落到一个叶子节点上,所以我们可以将所有同一个叶子结点的样本重组起来
L^(t)=∑i=1n[gift(xi)+12htft2(xi)]+Ω(ft)=∑i=1n[gift(xi)+12htft2(xi)]+γT+12λ∑j=1Twj2=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γT=12∑j=1T(Hj+λ)(wj+GjHj+λ)2+γT−12∑j=1TGj2Hj+λ\begin{aligned} \hat{ \mathcal { L }}^{(t)} & =\sum_{i=1}^n [g_if_t(x_i) + \frac12h_tf_t^2(x_i)] + \Omega(f_t) \\ & =\sum_{i=1}^n [g_if_t(x_i) + \frac12h_tf_t^2(x_i)] + \gamma T+\frac{1}{2}\lambda\sum\limits_{j=1}^{T}w_j^2 \\ & = \sum\limits_{j=1}^{T} [(\sum\limits_{i\in I_j}g_i)w_j+\frac{1}{2}(\sum\limits_{i\in I_j}h_i+\lambda) w_j^2]+\gamma T \\ & = \frac{1}{2}\sum\limits_{j=1}^{T} (H_j+\lambda)(w_j + \frac{G_j}{H_j+\lambda})^2+\gamma T -\frac{1}{2}\sum\limits_{j=1}^{T}\frac{G_j^2}{H_j+\lambda} \end{aligned} L^(t)​=i=1∑n​[gi​ft​(xi​)+21​ht​ft2​(xi​)]+Ω(ft​)=i=1∑n​[gi​ft​(xi​)+21​ht​ft2​(xi​)]+γT+21​λj=1∑T​wj2​=j=1∑T​[(i∈Ij​∑​gi​)wj​+21​(i∈Ij​∑​hi​+λ)wj2​]+γT=21​j=1∑T​(Hj​+λ)(wj​+Hj​+λGj​​)2+γT−21​j=1∑T​Hj​+λGj2​​​

其中,Gj=∑i∈IjgiG_j = \sum _{i \in I_j} g_iGj​=∑i∈Ij​​gi​是落入叶子节点i所有样本一阶梯度的总和,而Hj=∑i∈IjhiH_j = \sum _{i \in I_j} h_iHj​=∑i∈Ij​​hi​是落入叶子节点i所有样本二阶梯度的总和。

基于中学数学的原理,我们可以得知:

wj∗=−GjHj+λw_j^* = -\frac{G_j}{H_j+\lambda}wj∗​=−Hj​+λGj​​
时,损失函数最小。此时最终的损失函数大小为
L^∗=−12∑j=1TGj2Hj+λ+γT\hat{\mathcal { L }}^{*} =-\frac{1}{2}\sum\limits_{j=1}^{T}\frac{G_j^2}{H_j+\lambda}+\gamma TL^∗=−21​j=1∑T​Hj​+λGj2​​+γT

3.与牛顿法的关系

上面我们推导过程中,用到了二阶导数。而常见的基于二阶导数的优化方法就是牛顿法,下面我们看看与牛顿法的关系。
假设有一个函数f(x)f(x)f(x)二阶可微,我们对其进行泰勒展开到二阶,有
f(x)=f(xk)+f′(xk)(x−xk)+f′′(xk)(x−xk)2f(x) = f(x_k) + f'(x_k)(x-x_k) + f''(x_k)(x-x_k)^2f(x)=f(xk​)+f′(xk​)(x−xk​)+f′′(xk​)(x−xk​)2
上面的式子对x求导,并令导数等于0
f′(xk)+f′′(xk)(x−xk)=0f'(x_k) + f''(x_k)(x-x_k) = 0f′(xk​)+f′′(xk​)(x−xk​)=0

可以得到x的迭代公式为
x=xk−f′(xk)f′′(xk)x = x_k - \frac{f'(x_k)}{f''(x_k)}x=xk​−f′′(xk​)f′(xk​)​
这就是牛顿法的迭代公式。

对比一下叶子节点的取值方式
wj∗=−GjHj+λw_j^* = -\frac{G_j}{H_j+\lambda}wj∗​=−Hj​+λGj​​
与牛顿法唯一的区别在于,分母上二阶导多了一个正则项λ\lambdaλ,形式上完全一致,就是一阶导除以二阶导,与牛顿法的形式完全一致。

4.XGBoost的树分裂方式

上面推导了这么一大串,都是在分析叶子节点怎么取值。提升树系列的算法,还有很重要的一点是树的分裂方式。
首先我们回顾一下其他算法比如GBDT是怎么进行分裂的。标准的做法是选择MSE作为损失函数,采用启发式的方式来选择某个特征j的切分点s进行分裂。这个分裂的过程,并不一定总与损失函数相关。比如在分类树中,我们一般都会用对数损失函数(交叉熵)来评估模型的最终效果,这个时候树分裂的结果与损失函数就没有直接的关系。

XGBoost的树分裂是直接与损失函数相关的。在分裂的时候,会计算损失函数的增益Gain
Gain=12[GL2HL+λ+GR2HR+λ−(GL+GR)2HL+HR+λ]−γGain = \frac{1}{2} \left[\frac{G_L^2}{H_L+\lambda} + \frac{G_R^2}{H_R+\lambda} - \frac{(G_L + G_R)^2}{H_L + H_R+\lambda} \right] - \gammaGain=21​[HL​+λGL2​​+HR​+λGR2​​−HL​+HR​+λ(GL​+GR​)2​]−γ

上面这个式子其实很容易理解
(GL+GR)2HL+HR+λ\frac{(G_L + G_R)^2}{H_L + H_R+\lambda}HL​+HR​+λ(GL​+GR​)2​是分裂前最终的损失函数值,而
GL2HL+λ,GR2HR+λ\frac{G_L^2}{H_L+\lambda}, \frac{G_R^2}{H_R+\lambda} HL​+λGL2​​,HR​+λGR2​​
分别为分裂后的左右子树的损失函数值

那树进行分裂的时候,自然希望损失函数减少得越多越好。
前面我们推导出了损失函数最终的表达式

L^∗=−12∑j=1TGj2Hj+λ+γT\hat{\mathcal { L }}^{*} =-\frac{1}{2}\sum\limits_{j=1}^{T}\frac{G_j^2}{H_j+\lambda}+\gamma TL^∗=−21​j=1∑T​Hj​+λGj2​​+γT

那我们想要的结果就是分列前的损失函数减去分裂后的损失函数,差值最大,注意前面的负号,最后的分裂准则为
max(GL2HL+λ+GR2HR+λ−(GL+GR)2HL+HR+λ)max\left(\frac{G_L^2}{H_L+\lambda} + \frac{G_R^2}{H_R+\lambda} - \frac{(G_L + G_R)^2}{H_L + H_R+\lambda}\right)max(HL​+λGL2​​+HR​+λGR2​​−HL​+HR​+λ(GL​+GR​)2​)

5.XGBoost的各种Tricks总结

防止过拟合方法:
1.加入了正则项,对叶子节点数量,叶子节点分数加入了正则惩罚项。
2.加入了学习率,减少了单棵树影响,给后面树的优化留了更多空间。
3.列采样(特征采样),与随机森林类似,不仅来带来更好的效果,还可以提高运行速度。

缺失值的处理
在别的算法中,一般会使用中位数,均值或者两者进行融合计算的方式去处理缺失值。但是xgboost能处理缺失值,模型允许缺失值存在。
在寻找分裂点的时候,不对该特征缺失的样本进行遍历,只遍历该特征有的样。具体实现时,将该特征值缺失的样本分别分配到左叶子节点与右叶子节点,分别计算增益,然后选择增益较大的方向进行分裂即可。如果训练样本中没有缺失值,而预测时有缺失,默认将缺失值划分到右子节点。

分裂点的选择
并不把所有特征值间的间隔点作为候选分裂点,而是用分位数的方法将其作为分裂的候选集。

并行处理
XGBoost中虽然树之间是串行关系,但是同层级的节点可以并行。对于某个节点,节点内选择最佳分裂点与计算分裂点的增益是可以并行的。

基学习器(弱学习器)
传统的GBDT与CART树作为基分类器,XGBoost不仅支持CART树,还支持线性分类器,这个时候xgboost就相当于带L1与L2正则项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。

6.XGBoost 与GBDT的对比

主要的区别其实就是上面的Tricks。

参考文献

1.https://www.jianshu.com/p/ac1c12f3fba1

树算法系列之四:XGBoost相关推荐

  1. 树模型系列之XGBoost算法

    文章目录 树模型系列之XGBoost算法 概要 原理 损失函数 子树 xgboost算法流程总结 关键问题 缺失值处理(稀疏问题的分裂点查找 Sparsity-aware Split Finding) ...

  2. 面向对象的程序开发技术C++教学课件系列之四

    面向对象的程序开发技术C++教学课件系列之四 转载于:https://blog.51cto.com/hnxdd/13205

  3. [转]DPM2012系列之四:配置邮件报警功能

    DPM2012系列之四:配置邮件报警功能 源地址:http://543925535.blog.51cto.com/639838/1049285 ============================ ...

  4. 进程——Windows核心编程学习手札系列之四

    进程 --Windows核心编程学习手札系列之四 进程是一个正在运行的程序的实例,有两个部分组成:一个是操作系统用来管理进程的内核对象,内核对象是系统用来存放关于进程的统计信息的地方:另一个是地址空间 ...

  5. mongodb与java结合_MongoDB初探系列之四:MongoDB与Java共舞

    MongoDB初探系列之四:MongoDB与Java共舞 来源:互联网 作者:佚名 时间:2015-08-05 08:20 对各位注意到这个帖子的朋友说一声对不起,我不是故意的测试服务器一直没关,一忙 ...

  6. nginx系列之四:web服务器

    ** 前言 ** nginx系列之一:nginx入门 nginx系列之二:配置文件解读 nginx系列之三:日志配置 nginx系列之四:web服务器 nginx系列之五: 负载均衡 nginx系列之 ...

  7. ASP.NET企业开发框架IsLine FrameWork系列之四--DataProvider 数据访问(上)

    ASP.NET企业开发框架IsLine FrameWork系列之四--DataProvider 数据访问(上) 接上文 DataProvider是日常编程中最常用的Provider,它为项目提供了与数 ...

  8. Red Gate系列之四 SQL Data Compare 10.2.0.885 Edition 数据比较同步工具 完全破解+使用教程...

    Red Gate系列之四 SQL Data Compare 10.2.0.885 Edition 数据比较同步工具 完全破解+使用教程 Red Gate系列文章: Red Gate系列之一 SQL C ...

  9. SCCM2012系列之四,SCCM2012部署前的SQL Server准备

    SCCM2012系列之四,SCCM2012部署前的SQLServer准备 部署SCCM2012需要SQL数据库的支持.如果在生产环境,肯定是把数据库产品单独部署在服务器上,有可能还要考虑到高可用的因素 ...

  10. 隐马尔科夫模型(Hidden Markov Models) 系列之四

    隐马尔科夫模型(Hidden Markov Models) 系列之四 介绍(introduction) 生成模式(Generating Patterns) 隐含模式(Hidden Patterns) ...

最新文章

  1. android 长按赋值功能,android实现WebView中长按选中复制文本操作
  2. html加上 extjs右键,extjs 处理HTML事件和自定义事件
  3. Chapter1-1_Speech_Recognition(Overview)
  4. 2知识图谱的生命周期
  5. 如何在WPF 表格中嵌套按钮
  6. android build.gradle的repositories设置
  7. 谨慎设计方法签名(40)
  8. asp.net中前台javascript与c#函数相互调方法
  9. NodeJS链接MongDB
  10. win10 mfc 连接mysql_win10下使用c语言连接mysql
  11. 单利计算与复利计算程序
  12. 为了方便在微博上看小黄图,我写了一段JS
  13. 如何在网上买到下铺票2020_网上订票怎么选下铺
  14. iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
  15. 王者荣耀入门技能树-解答
  16. 用数字暗示我喜欢你_我喜欢数字!
  17. SAP中报表清单导出的常用方法
  18. python爬取笔趣阁
  19. STM32F105 UC/OS-II (B OSStartHang)问题
  20. android TextView 添加下划线

热门文章

  1. 冲刺第七天 12.3 MON
  2. java实现Excel数据导出
  3. EXCHANGE清除可恢复项目文件夹(就地电子数据展示和保留)
  4. disruptor:CAS实现高效(伪)无锁阻塞队列实践
  5. 终端安全求生指南(三)--脆弱性管理
  6. 《C++游戏编程入门(第4版)》——1.2 编写第一个C++程序
  7. 客户端用java api 远程操作HDFS以及远程提交MR任务(源码和异常处理)
  8. php通过header发送自定义数据
  9. 如何去除list中的重复元素
  10. Ubuntu 16.04重启Nautilus