之前文章分享了AdaBoost的算法原理和GBDT算法原理,这篇文章将讲解XGBoost,建议看本文之前,先看一下AdaBoost算法和GBDT算法的原理。码字不易,喜欢请点赞!!!

1.XGBoost简介
XGBoost自从提出以来,可谓就开始广为流传,并且在kaggle竞赛中屡获佳绩。在机器学习的算法中,XGBoost可谓是终极大杀器。本人学习XGBoost提出者陈天奇博士以及博客园刘建平大佬的文章后,根据自己的理解写了这篇博客,仅供自己学习和来着参考,如有错误,欢迎各位批评指正。
2.XGBoost损失函数
2.1GBDT损失函数
在上一篇文章中分享了GBDT算法的原理,其中提到,GBDT算法是每次通过拟合残差来进行预测,并且使用损失函数的负梯度作为当前模型的残差近似值。
rmi=−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
这里的负梯度其实就是损失函数的一阶泰勒展开。
泰勒展开说明:
首先,泰勒展开公式为:
f(x)=f(x0)+1!f′(x0)(x−x0)+2!f′′(x0)(x−x0)2+...+n!fn(x0)(x−x0)n+Rn(x)
并且GBDT算法的损失函数为:
Lm=i=1∑NL(yi,fm−1(xi)+hm(xi))
因此有GBDT算法的损失函数的泰勒展开为:
Lm=i=1∑NL(yi,fm−1(xi)+hm(xi))=i=1∑N[L(yi,fm−1(xi))+∂fm−1(xi)∂L(yi,fm−1(xi))hm(xi)+2!1∂fm−12(xi)∂L2(yi,fm−1(xi))hm2(xi)+...+n!1∂fm−1n(xi)∂Ln(yi,fm−1(xi))hmn(xi)+Rn(x)]
从损失函数的泰勒展开公式可以知道,GBDT使用的负梯度作为残差的近似值,其实就是使用的一阶泰勒展开。
2.2XGBoost损失函数
上一节说了GBDT的损失函数为Lm=∑i=1NL(yi,fm−1(xi)+hm(xi)),而XGBoost算法的损失函数,是在此基础上,添加了正则化项:
γJ+2λj=1∑Jwmj2
其中参数γ和λ为正则化系数,J为叶子节点数,而wmj和GBDT章节中的cmj是一个意思,表示第m棵树的第J个叶子节点的最优值,只是XGBoost的论文里用的是w表示叶子区域的值,因此这里和论文保持一致。
因此,可以得到XGBoost算法的损失函数为:
Lm=i=1∑NL(yi,fm−1(xi)+hm(xi))+γJ+2λj=1∑Jwmj2
优化目标为,损失函数极小化,得到第m棵树最优的J个叶子节点区域,以及每个叶子节点对应的最优解wmj。前面说过GBDT是拟合泰勒展开式的一阶导数,而XGBoost则期望直接基于损失函数的二阶泰勒展开式来求解,因此有下式:
Lm=i=1∑NL(yi,fm−1(xi)+hm(xi))+γJ+2λj=1∑Jwmj2≈i=1∑N[L(yi,fm−1(xi))+∂fm−1(xi)∂L(yi,fm−1(xi))hm(xi)+2!1∂fm−12(xi)∂L2(yi,fm−1(xi))hm2(xi)]+γJ+2λj=1∑Jwmj2
为了便于推到,令第i个样本在第m棵树上的一阶导数为:
gmi=∂fm−1(xi)∂L(yi,fm−1(xi))
令第i个样本在第m棵树上的二阶导数为:
lmi=∂fm−12(xi)∂L2(yi,fm−1(xi))
因此有:
Lm=i=1∑NL(yi,fm−1(xi)+hm(xi))+γJ+2λj=1∑Jwmj2≈i=1∑N[L(yi,fm−1(xi))+gmihm(xi)+21lmihm2(xi)]+γJ+2λj=1∑Jwmj2
损失函数中L(yi,fm−1(xi))为常数,对最小化无影响,可以去掉,因此有:
Lm≈i=1∑N[gmihm(xi)+21lmihm2(xi)]+γJ+2λj=1∑Jwmj2
并且对于第m棵树最优的j个叶子节点,其节点的值都为wmj,因此有:
Lm≈i=1∑N[gmihm(xi)+21lmihm2(xi)]+γJ+2λj=1∑Jwmj2=j=1∑J[xi∈Rmj∑gmiwmj+21xi∈Rmj∑lmiwmj2]+γJ+2λj=1∑Jwmj2=j=1∑J[(xi∈Rmj∑gmi)wmj+21(xi∈Rmj∑lmi+λ)wmj2]+γJ
此时,为了便于推导,令每个叶子节点处的一阶导数为:
Gmj=xi∈Rmj∑gmi
令每个叶子节点处的二阶导数为:
Lmj=xi∈Rmj∑lmi
因此,最终损失函数为:
Lm=j=1∑J[Gmjwmj+21(Lmj+λ)wmj2]+γJ
2.3XGBoost损失函数优化
前面GBDT原理小节提到,GBDT步骤是,先计算残差,然后根据残差拟合决策树,然后计算决策树每个叶子节点的最优取值。
在XGBoost中,将后面两步统一做,即一次求解出决策树最优的所有J个叶子节点区域,以及每个叶子节点处的最优值wmj。因此可以将这个问题拆分成两个问题:
(1)在得到决策树的叶子节点区域之后,如何计算最优值wmj?
(2)对当前决策树做子树分裂决策时,应该如何选择哪个特征和特征值进行分裂,使最终我们的损失函数Lm最小?
首先对于第一个问题,在得到决策树的叶子节点区域之后,最优值wmj可以通过对损失函数基于wmj求导,令导数为0,即可得到叶子节点区域最优解:
wmj=−Lmj+λGmj
在解决第二个为题时,首先将叶子节点区域最优解wmj代入损失函数得到:
Lm=−21j=1∑JLmj+λGmj2+γJ
在每次对某个叶子节点进行分裂时,将对在当前节点产生左子树和右子树,假设当前节点左右子树的一阶二阶导数和为GL,LL,GR,LR,因此每次分裂时,目标是最大化的减小损失函数,即最大化下式:
[−21(LL+LR)+λ(GL+GR)2+γJ]−[−21LL+λGL2−21LR+λGR2+γ(J+1)]
化简得到,我们期望最大化的是:
max21LL+λGL2+21LR+λGR2−21(LL+LR)+λ(GL+GR)2−γ
因此,每次进行左右子树分裂时,只需选择目标函数最大化的特征分裂处即可。
3.XGBoost算法流程
XGBoost算法流程如下:
输入:训练样本集T={(x1,y1),(x2,y2),...,(xN,yN)},其中,xi∈χ∈Rn,yi∈Y∈R;损失函数L(y,f(x));正则化系数λ和γ;
输出:强学习器f(x)
对于m=1,2,...,M
(1)计算第i个样本当前损失函数L基于fm−1(x)的一阶导数gmi和二阶导数lmi,计算所有样本的一阶导数和Gm=∑i=1Ngmi,二阶导数和Lm=∑i=1Nlmi
(2)基于当前节点尝试分裂决策树,默认分数score=0
对于特征序号k=1,2,...,K
(a)GL=0,HL=0
(b.1)将样本按特征k从小到大排列,依次取出第i个样本,依次计算当前样本放入左子树后,左右子树一阶和二阶导数和:
GL=GL+gmi,GR=G−GLLL=LL+lmi,LR=L−LL
(b.2)尝试更新最大的分数:
score=max{score,21LL+λGL2+21LR+λGR2−21(LL+LR)+λ(GL+GR)2−γ}
(3)基于最大score对应的划分特征和特征值分裂子树。
(4)如果最大score为0,则当前决策树建立完毕,计算所有叶子区域的wmj,得到弱学习器hm(x),更新强学习器ft(x),进入下一轮弱学习器迭代.如果最大score不是0,则转到第(2)步继续尝试分裂决策树。
参考文献
1.陈天奇论文:https://arxiv.org/pdf/1603.02754.pdf
2.陈天奇PPT:https://homes.cs.washington.edu/~tqchen/pdf/BoostedTree.pdf
3.刘建平关于XGBoost讲解的博客:https://www.cnblogs.com/pinard/p/10979808.html
4.本人的AdaBoost总结:https://blog.csdn.net/Asher117/article/details/103517786
5.本人的GBDT总结:https://blog.csdn.net/Asher117/article/details/103523968