题记
- Xgboost作为集成模型的一个代表,一直以优异的性能著称,很多Kaggle比赛的获奖者都非常偏爱使用这个模型。然而,这个模型背后的原理,却比一般的集成模型更为复杂和难以理解。 这次对Xgboost的推导过程和重点内容做一些整理,尽量通俗易懂,希望帮助大家更好地理解Xgboost。
学习残差
- Xgboost是一个由多个基模型构成的集成模型,每一个模型都在学习上一个模型的残差。因此,每多一棵树我们就离真实值更近了一步。最后,将所有模型的预测结果求和,作为最终的预测结果。
- 以上图为例,这次我们只看小boy,假设小boy的真实值为3,tree1的学习结果为2,则第二颗树是学习目标是真实值和预测值的差值(3-2)=1,而tree2学到了0.9。则最终对boy的预测值为2+0.9 = 2.9。是不是和真实值3非常接近?
- 关键点:
1.最终的预测值w,是由每颗树的结果求和得到的。
2.我们可以将一个预测结果拆分成 前面所有树的预测结果+新增树的预测结果
y^i(t)=k=1∑tfk(xi)=y^i(t−1)+ft(xi)
正则化项
- 为了避免过拟合的现象,我们从两个方面去约束Xgboost。
1.叶子节点个数 (避免树过于庞大)
2.对w进行L2正则化 (避免叶子节点上的值过分大和过分小)
Ω(ft)=γT+21λj=1∑Twj2
其中:
T为一颗树上的叶子节点个数
w 为叶子节点的权重值(可以理解成预测)
γ 和
λ 为代表约束力度的系数
- 举例 计算正则化项
Ω
目标函数
- 首先,我们想要优化的 目标函数 = 损失函数
l+正则化项
Ω
Obj(t)=i=1∑nl(yi,y^i(t))+i=1∑tΩ(fi)
- 将t棵树的总预测分解成前面t-1棵的总预测和最新的t棵的预测两部分,并且补充上常数项,得到
Obj(t)=i=1∑nl(yi,y^i(t−1)+ft(xi))+Ω(ft)+ constant
- 根据泰勒展开:
f(x+Δx)≃f(x)+f′(x)Δx+21f′′(x)Δx2
我们将
l展开
ft(x)看成
Δx,得到下面式子
Obj(t)≃i=1∑n[l(yi,y^i(t−1))+gift(xi)+21hift2(xi)]+Ω(ft)+ constant
其中gi 为一阶导
gi=∂y^(t−1)l(yi,y^(t−1)),hi为二阶导
hi=∂y^(t−1)2l(yi,y^(t−1))
- 对于boosting模型,前面t-1棵树的预测结果已经固定,因此损失函数也就固定,所以可以把
l(yi,y^i(t−1))看做一个常数,融合进常数项
constant ,同时,因为常数项不会影响我们的优化过程,所以我们将目标函数中的常数部分先暂时忽略,并且将正则化项展开,得到下式
i=1∑n[gift(xi)+21hift2(xi)]+λ21j=1∑Twj2+γT
- 将f(x)改写为w
=i=1∑n[giwq(xi)+21hiwq(xi)2]+λ21j=1∑Twj2+γT
注意:
1.此时的求和符号∑,代表的是对每一个样本计算,n代表样本个数。
2.正则化项中的w可以融合进前面的部分
对样本的遍历 —> 对叶子节点的遍历
因为我们每一个样本,最终都落到了某一个叶子节点上,所以这里我们就可以把对样本的遍历转化成对叶子节点的遍历。
j=1∑T⎣⎡⎝⎛i∈Ij∑gi⎠⎞wj+21⎝⎛i∈Ij∑hi+λ⎠⎞wj2⎦⎤+γT
注意:此时的求和符号∑,代表的是对每一个节点计算,T代表节点个数,
Ij代表第j个节点上的样本集合。
- 我们用G代表某一叶子节点上的一阶导数的和, H代表二阶导数的和
Gj=i∈Ij∑gi
Hj=i∈Ij∑hi
带入上面的式子,得到:
Obj(t)=j=1∑T[Gjwj+21(Hj+λ)wj2]+γT
看下中括号内的部分,变成了一个关于w的二次方程,二次方程求最小,x=-b/2a
wj=−Hj+λGj
我们把能让目标函数最小的这个w带回原式,求得Obj为:
Obj=−21j=1∑THj+λGj2+γT
属性划分
目标函数求出来了,我们如何对属性去进行划分呢?就是利用上面的目标函数。如何划分能让我们的目标函数的值降低更多,我们就如何划分。因此这里,用划分前的Obj减去划分后左右子树的Obj之和的差值,作为我们的属性划分准则,提1/2, 融负号,化简后结果如下:
(
γ可以视为加入新叶子结点引入的复杂度变化)
Gain=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2]−γ
这样,找到了使Gain最大的子树结构,我们就可以在此时进行分割了。
另外,Xgboost就是在这一步可以并行化,同时去算不同的分割方式带来的Gain值变化。
Xgboost重点总结
- 权重值w是通过最优化目标函数求出来的,而不是平均数众数等规则,因此预测效果更好,但容易过拟合。
- 为了解决上述过拟合问题引入正则化项,包括限制叶子节点个数,和对w的L2正则化,保证树的模型不会过于深入,w的预测值会相对平均。
- 支持自定义损失函数,由于利用泰勒展开将目标函数中的
l变成一阶导和二阶导的形式,因此只要能提供损失函数的一阶导和二阶导,就能带入Xgboost 。
- 支持并行化,在选择最佳分裂点时,不同分裂点的信息增益可以并行计算(得益于不同分裂点对G和H明确的影响),极大的提高了模型的训练速度。
对比 Xgboost / GBDT
- 损失函数:GBDT是一阶,XGB是二阶泰勒展开
- XGB的损失函数可以自定义,具体参考 objective 这个参数
- XGB的目标函数进行了优化,有正则项,减少过拟合,控制模型复杂度
预剪枝:预防过拟合
- GBDT:分裂到负损失,分裂停止 XGB:一直分裂到指定的最大深度(max_depth),然后回过头剪枝。如某个点之后不再正值,去除这个分裂。优点是,当一个负损失(-2)后存在一个正损失(+10),(-2+10=8>0)求和为正,保留这个分裂。
- XGB有列抽样/column sample,借鉴随机森林,减少过拟合
- 缺失值处理:XGB内置缺失值处理规则,用户提供一个和其它样本不同的值,作为一个参数传进去,作为缺失值取值。
- XGB在不同节点遇到缺失值采取不同处理方法,并且学习未来遇到缺失值的情况。
- XGB内置交叉检验(CV),允许每轮boosting迭代中用交叉检验,以便获取最优 Boosting_n_round 迭代次数,可利用网格搜索grid search和交叉检验cross validation进行调参。
GBDT使用网格搜索。
- XGB运行速度快:data事先安排好以block形式存储,利于并行计算。在训练前,对数据排序,后面迭代中反复使用block结构。
- 关于并行,不是在tree粒度上的并行,并行在特征粒度上,对特征进行Importance计算排序,也是信息增益计算,找到最佳分割点。
- 灵活性:XGB可以深度定制每一个子分类器
易用性:XGB有各种语言封装
扩展性:XGB提供了分布式训练,支持Hadoop实现
- 共同优点:
当数据有噪音的时候,树Tree的算法抗噪能力更强
树容易对缺失值进行处理
树对分类变量Categorical feature更友好