XGBoost

参考文献:XGBoost: A Scalable Tree Boosting System, Tianqi Chen, 2016.

XGBoost是Boosting算法的一种,假设原始样本为

D=\{(\vec{x}_i,y_i)\}_{i=1}^n,\;\;\vec{x}_i\in \mathbb{R}^m,\;y_i\in \mathbb{R}.

即样本量n,特征个数m。集成学习器形式为

\hat{y}=\phi(\vec{x})=\sum\limits_{t=1}^{T} f_t(\vec{x}),\;\; f_t \in \mathfrak{F}.

其中

\mathfrak{F}=\{f(\vec{x})=w_{q(\vec{x})}\},\;(q:\mathbb{R}^m \rightarrow \{1,...,L\},\vec{w} = (w_1,...,w_L) \in \mathbb{R}^L)

是回归树(CART)空间,L是树的叶子结点的数量,q是代表树的结构的函数,其将自变量映射到相应的叶子结点的编号上,\vec{w}是叶子结点的取值向量(w_j是第j个叶子结点的取值)。

假设l是可微凸函数,表示集成学习器和数据的拟合程度。我们将集成学习器的损失函数取成

\textup{loss}(\phi)=\sum\limits_{i=1}^{n} l(y_i,\hat{y}_i) + \sum\limits_{t=1}^{T} \Omega (f_t),

其中

\Omega (f) = \gamma L + \frac{1}{2} \lambda ||\vec{w}||^2,

是正则项,代表对树的复杂度的惩罚,其第一项代表对叶子结点数进行惩罚,第二项是对叶子结点的取值的平方和进行惩罚,前者和树的深度等价,都能反映一棵树的复杂度,后者太大则在集成学习器的预测中占比太高,也会过拟合。γλ是正则系数(非负)。

基学习器(回归树)训练准则

回顾Boosting算法的流程我们知道得到前t-1棵树后,我们要定义第t棵树的损失函数,假设树的结构q已知的情况下,其损失定义为

l^{(t)}=\sum\limits_{i=1}^{n} l(y_i,\hat{y}_i^{(t-1)}+f_t(\vec{x}_i)) + \Omega (f_t),

上标(t-1)表示第t-1步迭代时的预测值。我们对上式右边第一项进行二阶泰勒展开:

g_i^{(t)} = \frac{\partial l(y_i,z)}{\partial z}\big| _{z=\hat{y}_i^{(t-1)}},\;\;h_i^{(t)} = \frac{\partial ^2l(y_i,z)}{\partial z^2}\big| _{z=\hat{y}_i^{(t-1)}},

l^{(t)}\approx\sum\limits_{i=1}^{n} [l(y_i,\hat{y}_i^{(t-1)})+ g_i^{(t)}f_t(\vec{x}_i) + \frac{1}{2}h_i^{(t)}f_t^2(\vec{x}_i)]+\gamma L + \frac{1}{2} \lambda ||\vec{w}||^2.

由于前t-1棵树中不含未知参数,因此gh的值是已知的并且优化上述目标函数等价于优化

\tilde{l}^{(t)} =\sum\limits_{i=1}^{n} [ g_i^{(t)}f_t(\vec{x}_i) + \frac{1}{2}h_i^{(t)}f_t^2(\vec{x}_i)]+\gamma L + \frac{1}{2} \lambda ||\vec{w}||^2.

定义

I_j = \{i|q(\vec{x}_i)=j\},

即叶子结点j包含的实例集(instance set),则损失展开式可以写成

\tilde{l}^{(t)} = \sum\limits_{j=1}^{L} [ w_j\sum\limits_{i\in I_j}g_i^{(t)} + \frac{1}{2}w_j^2(\lambda+\sum\limits_{i\in I_j}h_i^{(t)})]+\gamma L,

由于我们假设l是可微凸函数,因此其二阶导大于零,因此上式中w_j的函数是关于未知参数的开口向上二次函数,我们可以求得w_j的最小值点

w_j^*=-\frac{\sum\limits_{i\in I_j}g_i^{(t)}}{\lambda+\sum\limits_{i\in I_j}h_i^{(t)}}

以及损失的最小值

\tilde{l}^{(t)^*} =-\frac{\big(\sum\limits_{i\in I_j}g_i^{(t)}\big)^2}{2\big(\lambda+\sum\limits_{i\in I_j}h_i^{(t)}\big)}+\gamma L.

注意上式的得出建立在我们已经确定了整棵树的结构q的前提下,其可以作为一个评分函数来衡量树结构q的质量(再次重申gh的值是已知的)。

显然不可能遍历所有可能得树结构q来选出损失最小的结构,实际上我们是使用贪婪算法来生成树的结构q的。假设我们确定了一个节点分裂后左右子结点上的样本子集(记为I_LI_R,并记I=I_LI_R),通过如下损失降低值(定义为分裂前的损失减去分裂后的损失)判断是否进行这一分裂:

l_{split}^{(t)} =\frac{1}{2}\left( \frac{\big(\sum\limits_{i\in I_L}g_i^{(t)}\big)^2}{\lambda+\sum\limits_{i\in I_L}h_i^{(t)}} + \frac{\big(\sum\limits_{i\in I_R}g_i^{(t)}\big)^2}{\lambda+\sum\limits_{i\in I_R}h_i^{(t)}}-\frac{\big(\sum\limits_{i\in I}g_i^{(t)}\big)^2}{\lambda+\sum\limits_{i\in I}h_i^{(t)}}\right )-\gamma .\displaystyle

若其大于0则分裂后损失降低,分裂,若其小于0则分裂后损失增加,不分裂。可以设置一个极小的正数当l_split小于此数值时就不分裂。上式中-γ是因为分裂后多了一个结点。

收缩和列采样

除了损失函数中的正则项外,我们还有另外两个防止过拟合的技术,即收缩(shrinkage)和列采样(column subsampling)。收缩在新产生的树前面加一个小于等于1的常数η(注意这里是第t棵树训练完了才给它乘以η然后加在前t-1步训练出的学习器上得到前t步训练出的学习器,然后再去训练第t+1棵树),降低每棵树的影响,让后面的树可以更好的提升模型。列采样则是通过随机选取部分特征用于树的训练(其他特征直接不考虑)来降低过拟合风险,列采样方式分为全局和局部两种,前者在树构建的初始阶段选取全部特征的子集,后续就只考虑这些被选中的特征,后者则是在划分每个结点时从全部特征中随机选取其子集,选中的特征只针对本结点的划分,后续结点用到的候选特征再重新选取。

树结构求解算法

精确贪婪算法

我们希望用l_split作为准则来划分回归树,考虑所有特征和所有可能的划分时,算法叫做精确贪婪算法(Basic Exact Greedy Algorithm),算法考虑某一连续特征时,会现将其按此特征大小将样本排序。

近似算法

精确贪婪算法是非常强大的,因为它列举了所有可能的分裂点。但是,当数据不能完全放入内存时,或在分布式设置中,此算法都没法实现,在这两种情况下,需要一个近似算法来替代精确算法。

我们将第k个特征和h_i^(t)的集合记为

D_k=\{(x_{i,k},h_i^{(t)})\}_{i=1}^n,

然后定义rank函数为

r_k(z) = \frac{\sum\limits_{(x,h)\in D_t,x< z}h}{\sum\limits_{(x,h)\in D_t}h},

即特征k的取值小于z的那些样品所占比例。我们想要找到备选的切分点

\{s_{k1}=\mathop{\mathrm{min}} \limits_{i} x_{ik},s_{k2},...,s_{kl}=\mathop{\mathrm{max}} \limits_{i} x_{ik}\},

使得

|r_{k}(s_{k,j})-r_{k}(s_{k,j+1})|<\epsilon.

本算法有两种变体,即全局分割和局部分割。全局分割在树构建的初始阶段提出所有的候选分割,并在所有的层次上使用相同的分割方案。局部分割(一般都用这个)在每次结点分裂后重新选定候选分割。全局方法比局部方法需要更少的建议步骤。然而,全局分割通常需要更多的候选点,因为候选点每次分裂后没有被refine。局部分割在每次结点分裂后都会refine候选点,因此更适合更深的树。局部分割需要的候选点个数较少,但如果有足够多的候选点,全局分割可以和局部分割一样准确。算法中候选点的多少通过epsilon的大小来反映,其越小则候选点越多。

稀疏感知分割

现实问题中输入x常常是稀疏的,稀疏性有多种可能的成因:1. 数据中存在缺失值;2. 统计中经常出现零项;3. 特征工程的产物,one-hot编码。重要的是要使算法意识到数据中的稀疏模式。稀疏感知分割(Sparsity-aware Split Finding)首先将缺失值样品放在一边不管,然后使用算法2的方式处理非缺失值。然后在每个树节点中添加一个默认方向(假设是右边R),将特征k的值缺失的个体全部分入默认方向R,先计算默认方向的反方向L(不含缺失值)的G_LH_L,然后用G-G_LH-H_L作为默认方向的G_RH_R值。默认方向取成左和右分别计算损失降低值,较大者作为默认方向。

总结

XGBoost算法作为Boosting算法的一种,其流程和其他Boosting算法相同,即逐个训练基学习器,然后将基学习器集成为最终学习器(XGBoost的集成方式为直接将基学习器相加)。

XGBoost的特色部分是其基学习器为回归树,回归树的训练方式为先用上节算法确定树结构,再用第一节结论得到每个叶子结点预测值。具体的,有了前t-1棵树的结果后,我们开始训练第t棵树,首先根据数据集和前t-1棵树,我们能够直接算出g_ih_i,然后从根节点开始进行结点分裂,分裂一个结点时挨个考虑每个特征,首先按一个特征的样本观测值将样品实例从小到大排序,然后考虑按候选切分点分裂后的损失降低值,取损失降低最多的候选切分点作为该特征的最佳切分点,然后对比所有特征的最佳切分点,取其中损失降低值最大的那个特征及其最佳切分点来分裂当前结点,其中可以考虑所有可能的候选切分点(精确算法,耗时多但准确),也可以按一定准则选取全部候选切分点的子集从中选取最佳切分点(近似算法,牺牲一定精确度换取耗时少)。结点停止分裂的准则可以是损失降低值小于一个给定正实数、结点上的数据集包含样品数小于一个给定正整数等。

注意XGBoost的树分裂是Level-wise的,即先分裂根节点(第一层),产生两个子结点(第二层)后,再依次分裂这两个子结点得到第三层的结点,这样依次按层分裂下去。直至一层中全部是叶子结点时停止。此方法容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但是不加区分的对待同一层的所有结点,实际上很多结点的分裂增益较低,没必要进行搜索和分裂,因此也会带来不必要的计算开销。

需要注意的时XGBoost只接受数值型特征,若是类别特征则需要先行预处理转化成数值型。

作为GBDT的改进,XGBoost与之不同之处包括:对损失函数做了2阶泰勒展开,并在损失函数中加入正则项抑制过拟合;每个弱学习器的学习过程是并行的;可以处理缺失值。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值