2014年,陈天奇博士提出了XGBoost算法,它可认为是在GBDT算法基础上的进一步优化。XGBoost(eXtreme Gradient Boosting)算法是Gradient Boosting算法的高效实现版本,因其在应用实践中表现出优良的效果和效率,因而也被工业界广为推崇。算法上的优化有:
工程上的优化有:
这里首先要讲解的就是一个一直令人很诧异的问题:怎么切割样本点?怎么得到分裂后子树的预测值?这个问题大家可以先去谅解一下这两篇博客:梯度提升树(GBDT)的问题思考、全方面讲解提升树及问题思考 - 统计学习基础。
在GBDT算法中,它是分两步:求出最优的所有J个叶子节点区域,再求出每个叶子节点区域的最优解。对于XGBoost,它期望把这两步合并在一起做,即一次求解出决策树最优的所有J个叶子节点区域和每个叶子节点区域的最优解 c t j c_{tj} ctj。我们来看下它是如何求解的,首先看下损失函数:
L t = ∑ i = 1 m L ( y i , f t − 1 ( x i ) + h t ( x i ) ) + Ω ( h t ) Ω ( h t ) = γ J + λ 2 ∑ j = 1 J w t j 2 L_t=\sum_{i=1}^{m}L(y_i,f_{t-1}(x_i)+h_t(x_i))+\Omega(h_t) \\ \Omega(h_t)=\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 Lt=i=1∑mL(yi,ft−1(xi)+ht(xi))+Ω(ht)Ω(ht)=γJ+2λj=1∑Jwtj2
这个公式有一个累加误差的过程, m m m表示样本个数。公式 Ω ( h t ) \Omega(h_t) Ω(ht)是一个正则化因子, J J J表示叶子区域个数, w t j w_{tj} wtj表示就是叶子区域预测值,跟GBDT中的 c t j c_{tj} ctj是一个意思,只不过在XGBoost用 w t j w_{tj} wtj表示。提出损失函数的目的就是求得使损失函数最小的叶子区域及预测值 w t j w_{tj} wtj,这里XGBoost没有和GBDT一样去拟合泰勒展开式的一阶导数,而是期望直接基于损失函数的二阶泰勒展开式来求解。现在我们来看看这个损失函数的二阶泰勒展开式:
L t = ∑ i = 1 m L ( y i , f t − 1 ( x i ) + h t ( x i ) ) + γ J + λ 2 ∑ j = 1 J w t j 2 = ∑ i = 1 m [ L ( y i , f t − 1 ( x i ) ) + L ′ ( y i , f t − 1 ( x i ) ) h t ( x i ) + 1 2 L ′ ′ ( y i , f t − 1 ( x i ) ) h t ( x i ) 2 ] + γ J + λ 2 ∑ j = 1 J w t j 2 \begin{aligned} L_t &=\sum_{i=1}^{m}L(y_i,f_{t-1}(x_i)+h_t(x_i))+\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 \\ &=\sum_{i=1}^{m} \bigg [L(y_i,f_{t-1}(x_i))+L^{'}(y_i,f_{t-1}(x_i))h_t(x_i)+\frac{1}{2}L^{''}(y_i,f_{t-1}(x_i))h_t(x_i)^2 \bigg ]+\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 \end{aligned} Lt=i=1∑mL(yi,ft−1(xi)+ht(xi))+γJ+2λj=1∑Jwtj2=i=1∑m[L(yi,ft−1(xi))+L′(yi,ft−1(xi))ht(xi)+21L′′(yi,ft−1(xi))ht(xi)2]+γJ+2λj=1∑Jwtj2
其中 L ′ ( y i , f t − 1 ( x i ) ) L^{'}(y_i,f_{t-1}(x_i)) L′(yi,ft−1(xi))、 L ′ ′ ( y i , f t − 1 ( x i ) ) L^{''}(y_i,f_{t-1}(x_i)) L′′(yi,ft−1(xi))分别是损失函数对 f t − 1 ( x i ) f_{t-1}(x_i) ft−1(xi)的一阶导、二阶导,记做:
g t i = L ′ ( y i , f t − 1 ( x i ) ) h t i = L ′ ′ ( y i , f t − 1 ( x i ) ) g_{ti} = L^{'}(y_i,f_{t-1}(x_i)) \qquad h_{ti}=L^{''}(y_i,f_{t-1}(x_i)) gti=L′(yi,ft−1(xi))hti=L′′(yi,ft−1(xi))
简化公式为:
L t = ∑ i = 1 m [ L ( y i , f t − 1 ( x i ) ) + g t i h t ( x i ) + 1 2 h t i h t ( x i ) 2 ] + γ J + λ 2 ∑ j = 1 J w t j 2 L_t = \sum_{i=1}^{m} \bigg [L(y_i,f_{t-1}(x_i))+g_{ti}h_t(x_i)+\frac{1}{2}h_{ti}h_t(x_i)^2 \bigg ]+\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 Lt=i=1∑m[L(yi,ft−1(xi))+gtiht(xi)+21htiht(xi)2]+γJ+2λj=1∑Jwtj2
我们再来思考,L(y_i,f_{t-1}(x_i))是一个常数,表示上一课树的损失函数值, h t ( x i ) h_t(x_i) ht(xi)是一个子树区域的预测值,其实也就是 w t j w_{tj} wtj,把 m m m个样本化成 J J J个样本子树区域,于是损失函数表示为:
L t = ∑ i = 1 m [ g t i h t ( x i ) + 1 2 h t i h t ( x i ) 2 ] + γ J + λ 2 ∑ j = 1 J w t j 2 = ∑ j = 1 J [ ∑ x i ∈ R t j g t i w t j + ∑ x i ∈ R t j 1 2 h t i w t j 2 ] + γ J + λ 2 ∑ j = 1 J w t j 2 = ∑ j = 1 J [ ∑ x i ∈ R t j g t i w t j + w t j 2 2 ( ∑ x i ∈ R t j h t i + λ ) ] + γ J \begin{aligned} L_t &=\sum_{i=1}^{m} \bigg [g_{ti}h_t(x_i)+\frac{1}{2}h_{ti}h_t(x_i)^2 \bigg ]+\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 \\ &=\sum_{j=1}^{J} \bigg [ \sum_{x_i \in R_{tj}}g_{ti}w_{tj}+\sum_{x_i \in R_{tj}}\frac{1}{2}h_{ti}w_{tj}^2 \bigg ]+\gamma J+\frac{\lambda}{2}\sum_{j=1}^{J}{w_{tj}}^2 \\ &=\sum_{j=1}^{J} \bigg [ \sum_{x_i \in R_{tj}}g_{ti}w_{tj}+\frac{w_{tj}^2}{2}(\sum_{x_i \in R_{tj}}h_{ti}+\lambda) \bigg ]+\gamma J \end{aligned} Lt=i=1∑m[gtiht(xi)+21htiht(xi)2]+γJ+2λj=1∑Jwtj2=j=1∑J[xi∈Rtj∑gtiwtj+xi∈Rtj∑21htiwtj2]+γJ+2λj=1∑Jwtj2=j=1∑J[xi∈Rtj∑gtiwtj+2wtj2(xi∈Rtj∑hti+λ)]+γJ
把每个子树区域的样本的一阶和二阶导数的和单独表示如下:
G t j = ∑ x i ∈ R t j g t i H t j = ∑ x i ∈ R t j h t i G_{tj}= \sum_{x_i \in R_{tj}}g_{ti} \qquad H_{tj}=\sum_{x_i \in R_{tj}}h_{ti} Gtj=xi∈Rtj∑gtiHtj=xi∈Rtj∑hti
于是损失函数最终的形式为:
L t = ∑ j = 1 J [ G t j w t j + w t j 2 2 ( H t j + λ ) ] + γ J L_t = \sum_{j=1}^{J} \bigg [ G_{tj}w_{tj}+\frac{w_{tj}^2}{2}(H_{tj}+\lambda) \bigg ]+\gamma J Lt=j=1∑J[Gtjwtj+2wtj2(Htj+λ)]+γJ
得到了最终的损失函数,如何一次求解出决策树最优的所有J个叶子节点区域和每个叶子节点区域的最优解 w t j w_{tj} wtj呢?
我们得到了最终的损失函数,我们想通过求解损失函数最小值来得到决策树,从而得到样本被划分的子树区域及子树区域的预测值,所以我们的优化公式如下:
min L t = ∑ j = 1 J [ G t j w t j + w t j 2 2 ( H t j + λ ) ] + γ J G t j = ∑ x i ∈ R t j g t i H t j = ∑ x i ∈ R t j h t i \min L_t = \sum_{j=1}^{J} \bigg [ G_{tj}w_{tj}+\frac{w_{tj}^2}{2}(H_{tj}+\lambda) \bigg ]+\gamma J \\ G_{tj}= \sum_{x_i \in R_{tj}}g_{ti} \qquad H_{tj}=\sum_{x_i \in R_{tj}}h_{ti} minLt=j=1∑J[Gtjwtj+2wtj2(Htj+λ)]+γJGtj=xi∈Rtj∑gtiHtj=xi∈Rtj∑hti
但对着这个损失函数求解最小值似乎一筹莫展,根本无从下手,其实还是回到了一开始说的那两个问题:
这个问题在GBDT算法中也涉及到了,它是通过穷举的方式通过均方误差来划分子树,我们来看下XGBoost如何来做,首先我们通过 L t L_t Lt对 w t j w_{tj} wtj求导,导数等于0求得极值,得到:
w t j = − G t j H t j + λ w_{tj}=-\frac{G_{tj}}{H_{tj}+\lambda} wtj=−Htj+λGtj
带入到原损失函数中得到:
L t = − 1 2 ∑ j = 1 J G t j 2 H t j + λ + γ J L_{t}=-\frac{1}{2}\sum_{j=1}^{J}\frac{G_{tj}^2}{H_{tj}+\lambda}+\gamma J Lt=−21j=1∑JHtj+λGtj2+γJ
转换后的损失函数就变成了如何来分裂特征获得子树区域,XGBoost使用贪心算法来求解此问题,算法思想:如果我们每次做左右子树分裂时,可以最大程度的减少损失函数的损失就最好了。怎么衡量这个损失函数的损失?用如下公式:
− 1 2 ( G L + G R ) 2 H L + H R + λ − [ − 1 2 G L 2 H L + λ − 1 2 G R 2 H R + λ + λ ( J + 1 ) ] + γ J -\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}-\bigg[-\frac{1}{2}\frac{G_{L}^2}{H_{L}+\lambda}-\frac{1}{2}\frac{G_{R}^2}{H_{R}+\lambda}+\lambda (J+1)\bigg]+\gamma J −21HL+HR+λ(GL+GR)2−[−21HL+λGL2−21HR+λGR2+λ(J+1)]+γJ
G L 、 G R G_L、G_R GL、GR是左右子树的一阶导之和, H L 、 H R H_L、H_R HL、HR是左右子树的二阶导之和。这个公式怎么来的?为什么是这样的形式?目前还不清楚,后面再解析。整理上式,化简为:
max 1 2 G L 2 H L + λ + 1 2 G R 2 H R + λ − 1 2 ( G L + G R ) 2 H L + H R + λ − γ \max \qquad \frac{1}{2}\frac{G_{L}^2}{H_{L}+\lambda}+\frac{1}{2}\frac{G_{R}^2}{H_{R}+\lambda}-\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}-\gamma max21HL+λGL2+21HR+λGR2−21HL+HR+λ(GL+GR)2−γ
输入:训练集样本 I = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x m , y m ) } I=\{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\} I={(x1,y1),(x2,y2),...,(xm,ym)},最大迭代次数 T T T,损失函数 L L L,正则化系数 λ , γ \lambda,\gamma λ,γ
输出:强学习器 f ( x ) f(x) f(x)
算法流程:
对迭代轮数 t = 1 , 2 , . . . T t=1,2,...T t=1,2,...T有:
1、计算第i个样本 ( i = 1 , 2 , . . m ) (i=1,2,..m) (i=1,2,..m)在当前轮损失函数L基于 f t − 1 ( x i ) f_{t-1}(xi) ft−1(xi)的一阶导数 g t i g_{ti} gti,二阶导数 h t i h_{ti} hti,计算所有样本的一阶导数和 G t G_t Gt和 H t H_t Ht。
2、基于当前节点尝试分裂决策树,默认分数score=0,对特征序号 k = 1 , 2... K k=1,2...K k=1,2...K:
a、 G L = 0 G_L=0 GL=0和 H L = 0 H_L=0 HL=0,将样本按特征k从小到大排列,依次取出第i个样本,依次计算当前样本放入左子树后,左右子树一阶和二阶导数和:
G L = G L + g t i , G R = G − G L H L = H L + h t i , H R = H − H L G_L=G_L+g_{ti},G_R=G-G_L \\ H_L=H_L+h_{ti},H_R=H-H_L GL=GL+gti,GR=G−GLHL=HL+hti,HR=H−HL
b、尝试更新最大的分数:
s c o r e = m a x ( s c o r e , 1 2 G L 2 H L + λ + 1 2 G R 2 H R + λ − 1 2 ( G L + G R ) 2 H L + H R + λ − γ ) score = max(score,\frac{1}{2}\frac{G_{L}^2}{H_{L}+\lambda}+\frac{1}{2}\frac{G_{R}^2}{H_{R}+\lambda}-\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}-\gamma) score=max(score,21HL+λGL2+21HR+λGR2−21HL+HR+λ(GL+GR)2−γ)
3、 基于最大score对应的划分特征和特征值分裂子树。
4)、如果最大score为0,则当前决策树建立完毕,计算所有叶子区域的 w t j w_{tj} wtj, 得到弱学习器 h t ( x ) h_t(x) ht(x),更新强学习器 f t ( x ) f_t(x) ft(x),进入下一轮弱学习器迭代.如果最大score不是0,则转到第2步继续尝试分裂决策树。
疑问:
看到有些博客里讲解了XGBoost关于缺省值的问题,我们假设有些样本特征值是缺省的,因为缺省的,所以这些样本的一阶导、二阶导都是没有的,那么这些样本是应该放在左子树还是右子树?原本是假定这些样本值是在右子树的。
这些问题,有些问题是咨询刘建平老师的,在他的博客里留言的,参考博客里就是他的一篇文章。
XGBoost算法原理小结