1 XGBoost算法简介

XGBoost(Extreme Gradient Boosting)算法是陈天奇博士于2016年发表的论文《 XGBoost:A Scalable Tree Boosting System》中正式提出的。XGBoost在GBDT算法的基础上作出了一系列的优化,如在损失函数的计算中增加了二阶导数,增加了正则项,一定程度上的并行计算等。

XGBoost算法在机器学习中有着广泛的应用,在机器学习大赛中有着不错的表现。

XGBoost算法支持回归算法与分类算法。本文介绍其中的回归算法。

2 关于目标函数

2.1 损失函数

f_{t}(x)表示第t轮预测值,w_{t}(x)表示第t棵树在样本x处的取值(权重),L(y,f_{t}(x))表示第t轮的损失函数,损失函数L(y,f_{t}(x))二阶可导。

L(y,f_{t}(x))二阶泰勒展开:

L(y,f_{t}(x))=L(y,f_{t-1}(x)+w_{t}(x))=L(y,f_{t-1}(x))+\frac{\partial L(y,f(x))}{\partial f(x)}|_{f(x)=f_{t-1}(x)}w_{t}(x)+\frac{\partial^2 L(y,f(x))}{2\partial f^2(x)}|_{f(x)=f_{t-1}(x)}w_{t}^{2}(x)+constant

g_{t}=\frac{\partial L(y,f(x))}{\partial f(x)}|_{f(x)=f_{t-1}(x)}h_{t}=\frac{\partial^2 L(y,f(x))}{\partial f^2(x)}|_{f(x)=f_{t-1}(x)}

2.2 目标函数

针对样本构造目标函数,在第t轮时,

Obj=\sum_{i=1}^{N}L(y_{i},f_{t}(x_{i}))

=\sum_{i=1}^{N}(L(y_{i},f_{t-1}(x_{i}))+\frac{\partial L(y_{i},f(x))}{\partial f(x)}|_{f(x)=f_{t-1}(x_{i})}w_{t}(x_{i})+\frac{\partial^2 L(y_{i},f(x))}{2\partial f^2(x)}|_{f(x)=f_{t-1}(x_{i})}w_{t}^{2}(x_{i})+constant)

=\sum_{i=1}^{N}(L(y_{i},f_{t-1}(x_{i}))+\sum_{i=1}^{N}\frac{\partial L(y_{i},f(x))}{\partial f(x)}|_{f(x)=f_{t-1}(x_{i})}w_{t}(x_{i})+\sum_{i=1}^{N}\frac{\partial^2 L(y_{i},f(x))}{\partial f^2(x)}|_{f(x)=f_{t-1}(x_{i})}w_{t}^{2}(x_{i})+constant

=\sum_{i=1}^{N}(L(y_{i},f_{t-1}(x_{i}))+\sum_{i=1}^{N}g_{t,i}w_{t}(x_{i})+\frac{1}{2}\sum_{i=1}^{N}h_{t,i}w_{t}^{2}(x_{i})+constant
在第t轮迭代时,f_{t-1}(x_{i})已知, constant为常数,要使得目标函数最小,仅需要上式中第2、3项的和最小即可。因此,可将目标函数改造成:

Obj=\sum_{i=1}^{N}[g_{t,i}w_{t}(x_{i})+\frac{1}{2}h_{t,i}w_{t}^{2}(x_{i})]

2.3 添加正则项

在第t棵树中,第j个叶子节点对应的样本序号的集合I_{j}=\left \{ i|q(x_{i})=j \right \},在i\in I_{j}时,w_{t}(x_{i})=w_{j}

利用树的复杂度定义正则项,在第t轮迭代时,

\Omega =\gamma J_{t}+\frac{1}{2}\lambda \sum_{j=1}^{J_{t}}w_{j}^{2},其中J_{t}表示第t棵树叶子节点的个数,w_{j}表示第t棵树第j个叶子节点的取值(权重);\gamma,\lambda为设定的参数,且均大于0。

考虑到模型的泛化能力,在目标函数中增加正则项\Omega,则

Obj=\sum_{i=1}^{N}[g_{t,i}w_{t}(x_{i})+\frac{1}{2}h_{t,i}w_{t}^{2}(x_{i})]+\Omega

将正则项代入目标函数:

Obj=\sum_{i=1}^{N}[g_{t,i}w_{t}(x_{i})+\frac{1}{2}h_{t,i}w_{t}^{2}(x_{i})]+(\gamma J_{t}+\frac{1}{2}\lambda \sum_{j=1}^{J_{t}}w_{j}^{2})

Obj=\sum_{j=1}^{J_{t}}[\sum_{i\in I_{j}}^{}(g_{t,i}w_{t}(x_{i})+\frac{1}{2}h_{t,i}w_{t}^{2}(x_{i}))]+(\gamma J_{t}+\frac{1}{2}\lambda \sum_{j=1}^{J_{t}}w_{j}^{2})

=\sum_{j=1}^{J_{t}}\left [ (\sum_{i\in I_{j}}^{}g_{t,i})w_{j}+\frac{1}{2}(\sum_{i\in I_{j}}^{}h_{t,i})w_{j}^{2}\right ]+\gamma J_{t}+\frac{1}{2}\lambda \sum_{j=1}^{J_{t}}w_{j}^{2}

=\sum_{j=1}^{J_{t}}\left [ (\sum_{i\in I_{j}}^{}g_{t,i})w_{j}+\frac{1}{2}(\sum_{i\in I_{j}}^{}h_{t,i}+\lambda )w_{j}^{2}\right ]+\gamma J_{t}

G_{j}=\sum_{i\in I_{j}}^{}g_{t,i},H_{j}=\sum_{i\in I_{j}}^{}h_{t,i},则

Obj=\sum_{j=1}^{J_{t}}\left [ G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda )w_{j}^{2}\right ]+\gamma J_{t}

2.4 目标函数最优解

从目标函数的表达式可以看出,在第j个叶子节点时的表达式是关于w_{j}的一元二次函数,在w_{j}=w_{j}^{*}=-\frac{G_{j}}{2*\frac{1}{2}(H_{j}+\lambda )}=-\frac{G_{j}}{H_{j}+\lambda }时目标函数取得极值。

此时,Obj=-\frac{1}{2}\sum_{j=1}^{J_{t}}\frac{G_{j}^{2}}{H_{j}+\lambda }+\gamma J_{t}

3 树的生成

XGBoost树的节点分裂,支持贪心算法和近似算法,这里介绍贪心算法。

3.1 节点分裂

假设叶子节点继续分裂分成左右(L,R)两个叶子节点。分裂前叶子节点的个数J_{t}为1,分裂后变为2。在第t棵树中,分裂后的G_{j}分别记为G_{L},G_{R},分裂后的H_{j}分别记为H_{L},H_{R}

则可计算分裂前后的目标函数增益:

Gain=Obj_{L+R}-(Obj_{L}+Obj_{R})

=-\frac{1}{2}\frac{(G_{L}+G_{R})^{2}}{H_{L}+H_{R}+\lambda }+\gamma -(-\frac{1}{2}\frac{G_{L}^{2}}{H_{L}+\lambda }+\gamma -\frac{1}{2}\frac{G_{R}^{2}}{H_{R}+\lambda }+\gamma)

=\frac{1}{2}(\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 })-\gamma

对于所有可能的分裂,计算上述增益,以增益最大的分裂作为本次的节点分裂。

对于分裂后的叶子节点,继续按照上述贪心算法进行分裂,直至无法分裂或满足停止条件(如增益小于指定值、叶子节点的样本数量限制、树的深度达到指定值等),生成本轮决策树。

3.2 样本取值

在上述生成树的叶子节点中,在第j个叶子节点的取值w_{j}=w_{j}^{*}=-\frac{G_{j}}{H_{j}+\lambda }

4 XGBoost回归算法过程

4.1 输入输出

1)输入

训练样本集:D=\left \{ (x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N}) \right \}

2)输出

最终回归树f(x)

4.2 模型初始化

设定\lambda ,\gamma

假设初始化的弱学习器f_{0}(x_{i})=c,代价函数cost(c)=\sum_{i=1}^{N}L(y_{i},c)

c=\underset{c}{arg\min }\sum_{i=1}^{N}L(y_{i},c)

如当损失函数是平方损失函数时,c=\frac{1}{N}\sum_{i=1}^{N}y_{i}

模型的初始化会影响迭代效率。

4.3 进行迭代

对于t=1,2,...,T轮迭代:

1)计算负梯度

对于第i个样本,其负梯度r_{t,i}=-\frac{\partial L(y_{i},f(x))}{\partial f(x)}|_{f(x)=f_{t-1}(x_{i})}

对于回归算法,一般选择平方损失函数,即L(y,f(x))=\frac{1}{2}(y-f(x))^{2},则

r_{t,i}=y_{i}-f_{t-1}(x_{i})

2)利用负梯度生成回归树

利用负梯度构建新的数据集D_{t}=\left \{ (x_{1},r_{t,1}),(x_{2},r_{t,2}),...,(x_{N},r_{t,N}) \right \}

计算g_{t,i},h_{t,i},i=1,2,...,N,计算G_{j},H_{j}

按照前述“树的生成”中的方法,生成本轮决策树w_{t}(x)

叶子节点的区域为R_{t,j},j=1,2,...,J_{t},其取值w_{t,j}=-\frac{G_{j}}{H_{j}+\lambda }

3)更新强学习器

f_{t}(x)=f_{t-1}(x)+w_{t}(x)=f_{t-1}(x)+\sum_{j=1}^{J_{t}}w_{t,j}I(x\in R_{t,j})

在不满足停止条件时,继续迭代。

在模型实现过程中,一般会增加一个学习率。

   4) 得到最终学习器

在第T轮迭代时:当目标函数小于指定值或满足其它设定的停止条件(如迭代次数、分类器在训练集或测试集上的性能等)时,迭代停止。

f(x)=f_{T}(x)=f_{0}(x)+\sum_{t=1}^{T}\sum_{j=1}^{J_{t}}w_{t,j}I(x\in R_{t,j})

5、算法代码实现

import pandas as pd
import numpy as np
from xgboost import XGBRegressor
from sklearn import datasets
#选择sklearn中的数据集
diabetes = datasets.load_diabetes()
X,y = diabetes.data,diabetes.target
#选择默认参数训练模型
xgb = XGBRegressor()
xgb.fit(X,y)
XGBRegressor(base_score=0.5, booster='gbtree', callbacks=None,
             colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
             early_stopping_rounds=None, enable_categorical=False,
             eval_metric=None, gamma=0, gpu_id=-1, grow_policy='depthwise',
             importance_type=None, interaction_constraints='',
             learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4,
             max_delta_step=0, max_depth=6, max_leaves=0, min_child_weight=1,
             missing=nan, monotone_constraints='()', n_estimators=100, n_jobs=0,
             num_parallel_tree=1, objective='reg:squarederror',
             predictor='auto', random_state=0, reg_alpha=0, ...)
xgb.predict(X[0:10])
array([151.23256 ,  75.027435, 141.04771 , 205.8506  , 135.08458 ,
        97.08945 , 137.44916 ,  63.018257, 109.95988 , 309.85986 ],
      dtype=float32)

6、算法说明

1、XGBoost算法将损失函数二阶泰勒展开,这是该算法与GBDT算法的重大差异。这一做法较大的提升了模型的效果。

2、XGBoost算法在模型中增加了正则项,减缓了模型的过拟合风险,提高了模型的泛化能力。

3、XGBoost算法不仅支持贪心算法,还支持近似算法以提升运算效率。

4、XGBoost算法在一定程度上实现了并行处理。在特征层面实现了并行运算。

5、XGBoost算法引入了特征子采样。

6、XGBoost算法支持稀疏值处理、缺失值处理等。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐