集成学习(Ensemble Larning)本身不是一个单独的机器学习算法,是通过构建并结合多个机器学习器来完成学习任务的思想。通常的集成学习的方法指的是同质个体学习器。同质个体学习器使用最多的模型是CART决策树和神经网络。按照个体学习器之间是否存在依赖关系可以分为两类,第一个是个体学习器之间存在强依赖关系,一系列个体学习器基本都需要串行生成,代表算法是Boosting系列算法;第二个是个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成,代表算法是Bagging和随机森林(Random Forest)系列算法。
·Boosting
Boosting算法原理可以通过下图进行展示:
在上图中可以看出Boosting算法的工作原理是:
- 从训练集用初始权重 $ D(1) $ 进行初始化,并用带权重的数据集训练出一个弱学习器1,根据弱学习的学习误差率 $ e1 $ 的表现来更新训练样本的权重 $ D(2) $ ,使得之前弱学习器1学习误差率高的训练样本点的权重变大;让这些误差率高的点在后面的弱学习器2中得到更多的重视。
- 基于调整权重后的训练集来训练弱学习器2。重复步骤1,直到弱学习器数达到事先指定的数目 $ T $ ,最终将这 $ T $ 个弱学习器通过集合策略进行整合,得到最终的强学习器。
Boosting系列算法里最著名算法主要有AdaBoost算法和提升树(boosting tree)系列算法。提升树系列算法里面应用最广泛的是梯度提升树(Gradient Boosting Tree)。
AdaBoost(Adaptive boosting)算法:刚开始训练时对每一个训练例赋相等的权重,然后用该算法对训练集训练 $ t $ 轮,每次训练后,对训练失败的训练例赋以较大的权重,也就是让学习算法在每次学习以后更注意学错的样本,从而得到多个预测函数。通过拟合残差的方式逐步减小残差,将每一步生成的模型叠加得到最终模型。
GBDT(Gradient Boost Decision Tree),每一次的计算是为了减少上一次的残差,GBDT在残差减少(负梯度)的方向上建立一个新的模型。
·Bagging
Bagging的算法原理和Boosting的算法原理有所不同。
从上图可以看出,Bagging的弱学习器之间的确没有Boosting那样的联系。它的特点在“随机采样”。那么什么是随机采样?
随机采样(bootsrap)就是从我们的训练集里面采集固定个数的样本,但是每采集一个样本后,都将样本放回。也就是说,之前采集到的样本在放回后有可能继续被采集到。对于我们的Bagging算法,一般会随机采集和训练集样本数 $ m $ 一样个数的样本。这样得到的采样集和训练集样本的个数相同,但是样本内容不同。如果我们对有 $ m $ 个样本训练集做 $ T $ 次的随机采样,,则由于随机性, $ T $ 个采样集各不相同。
GBDT的子采样是无放回采样,而Bagging的子采样是有放回采样。
对于一个样本,在某一次含 $ m $ 个样本的训练集的随机采样中,每次被采到的概率是 $ \frac{1}{m} $ ,不被采集到的概率为 $1- \frac{1}{m} $ 。如果 $ m $ 采样都没有被采集到的概率是 $ (1-\frac{1}{m})^{m} $。当 $ m\rightarrow\infty $ 时, $ (1-\frac{1}{m})^{m} \rightarrow \frac{1}{e}\approx 0.368 $ 。也就是说,在Bagging的每轮采样中大约有 $ 36.8\% $ 的数据没有被采样集采集。
对于这部分没有被采集到的数据,通常被称为袋外数据(Out Of Bag,OOB)。这些数据没有参与训练集模型的拟合,因此可以用来检测模型的泛化能力。
决策树和神经网络。
Bagging的集合策略也比较简单。对于分类问题,通常使用简单投票法,得到最多票数的类别或者类别之一为最终的模型输出。对于回归问题,通常使用简单平均法,对T个弱学习器得到的回归结果进行算术平均得到最终的模型输出。
由于Bagging算法每次都进行采样来训练模型,因此泛化能力很强,对于降低模型的方差很有作用。当然对于训练集的拟合程度就会差一些,也就是模型的偏倚会大一些。
Bagging的算法流程:
输入:样本集 $ D=\left \{ (x,y_{1}),(x_{2},y_{2}),...(x_{m},y_{m}) \right \} $ ,弱学习器算法,弱学习器迭代次数 $ T $
输出:最终的强分类器 $ f(x) $
1)对于 $ t=1,2,3,\cdots ,T $ :
a)对于训练集进行第 $ t $ 次随机采样,共采集 $ m $ 次,得到包含 $ m $ 个样本的采样数据集 $ Dt $
b)用采样数据集 $ Dt $ 训练第 $ t $ 个弱学习器 $ Gt(x) $
2)如果是分类算法的预测,则 $ T $ 个弱学习器投出最多票数的类别或者类别之一为最终的输出类别;如果是回归算法,则 $ T $ 个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。
·Boosting和Bagging的区别
| Boosting | Bagging |
样本选择 | 每一轮的训练集不变,只是训练集中每个样本在分类器中的权重发生变化。权重是根据上一轮分类结果进行调整 | 训练集是有放回的选取,从原始数据集中选出的各轮训练集之间是独立的 |
样本权重 | 根据错误率不断调整样本的权重,错误率越大样本的权重越大 | 使用均匀采样,每个样本的权重相等 |
预测函数 | 每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重 | 所有的预测器的权重相等 |
并行计算 | 各个预测函数只能顺序生成,因为后一个模型参数需要前一轮的模型结果 | 各个预测器可以并行生成 |
·随机森林
随机森林(Random Forest,RF)是Bagging算法的进阶版本。随机森林算法相对于Bagging算法的改进点在于:
1.随机森林采用了CART决策树作为弱学习器;
2.在使用决策树的基础上,随机森林对决策树的构建方面进行了改进。对于普通的决策树,通常是在节点上所有的 $ n $ 个样本特征中选择一个最优的特征来做决策树的左右子树的划分。在随机森林中,是通过随机选择节点上的一部分样本特征,这个数字小于 $ n $ ,假设为 $ n_{sub}$ ,然后在这些随机选择的 $ n_{sub} $ 个样本特征中,选择一个最优的特征来做决策树的左右子树的划分。这样可以进一步的增强模型的泛化能力。
如果 $ n_{sub}=n $ ,则此时构建的随机森林和普通的CART决策树没有区别。 $ n_{sub} $ 越小,模型越健壮,此时模型对于训练集的拟合度也会变差。也就是说, $ n_{sub} $ 越小,模型的方差会减小,但是偏倚会增大。在实际项目中,一般会通过交叉验证调参获取一个合适的 $ n_{sub} $ 值。
随机森林算法流程:
输入:样本集 $ D=\left \{ (x,y_{1}),(x_{2},y_{2}),...(x_{m},y_{m}) \right \} $ ,弱学习器迭代次数 $ T $
输出:最终的强分类器 $ f(x) $
1)对于 $ t=1,2,3,\cdots ,T $ :
a)对于训练集进行第 $ t $ 次随机采样,共采集 $ m $ 次,得到包含 $ m $ 个样本的采样数据集 $ Dt $
在训练决策树模型节点的时候,在节点上所有的样本特征中选择一部分特征,在这些随机选取的部分样本特征中选择一个最优的特征来做决策树的左右子树的划分。
2)如果是分类算法的预测,则 $ T $ 个弱学习器投出最多票数的类别或者类别之一为最终的输出类别;如果是回归算法,则 $ T $ 个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。
用我们常说的话来形容这个思想就是“三个臭皮匠赛过诸葛亮”。
随机森林的主要优点有:
1) 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。
2) 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型。
3) 在训练后,可以给出各个特征对于输出的重要性
4) 由于采用了随机采样,训练出的模型的方差小,泛化能力强。
5) 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单。
6) 对部分特征缺失不敏感。
RF的主要缺点有:
1)在某些噪音比较大的样本集上,RF模型容易陷入过拟合。
2) 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。
·GBDT
GBDT也是集成学习Boosting算法族中的一种算法。和传统的Adaboost有很大的不同。Adaboost算法是利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。
在GBDT的迭代中,假设前一轮的迭代得到的强学习器是 $ f_{t-1} $ ,损失函数是 $ L(y,f_{t-1}(x))) $ ,本轮迭代的目标是找到一个CART回归决策树模型的弱学习器 $ h_{t}(x) $ ,让本轮的损失函数 $ L(y,f_{t}(x)=f_{t-1}(x)+h_{t}(x)) $ 最小。也就是说,本轮找到的决策树使得损失尽量的变小。
1.GBDT的负梯度拟合
针对这个问题,Freidman提出了用损失函数的负梯度来拟合本轮损失的近似值,从而拟合CART决策树。第 $ t $ 轮的第 $ i $ 个样本的损失函数的负梯度表示为:
$$
\begin{align}
r_{ti}=-\left [ \frac{\partial L(y_{i},f(x_{i}))}{\partial f(x_{i})} \right ]_{f(x)=f_{t-1}(x)}\nonumber
\end{align}
$$
利用 $ (x_{i},r_{ti})(i=1,2,3\cdots ,m) $ ,可以拟合出一棵决策回归树。得到了第 $ t $ 棵回归树。其对应的叶节点区域 $ R_{tj},j=1,2,3,\cdots ,J $ 。其中 $ J $ 为叶子节点的个数。
针对每一个叶子节点里的样本,求出使得损失函数最小,也就是拟合叶子节点最好的输出值 $ c_{tj} $ 如下:
$$
\begin{align}
c_{tj}=\underset{c}{\underbrace{argmin}}\sum_{x_{i}\in R_{tj}}{L(y_{i},f_{t-1}(x_{i})+c)}\nonumber
\end{align}
$$
这样就得到了本轮的决策拟合函数如下:
$$
\begin{align}
h_{t}(x)=\sum_{j=1}^{J}c_{tj}I(x\in R_{tj})\nonumber
\end{align}
$$
从而本轮最终的强学习器的表达式如下:
$$
\begin{align}
f_{t}(x)=f_{t-1}(x)+\sum_{j=1}^{J}c_{tj}I(x\in R_{tj})\nonumber
\end{align}
$$
这样不论是分类问题还是回归问题,就可以通过对损失函数的负梯度来拟合,就可以用GBDT来解决分类回归问题。区别仅仅在于损失函数不同导致的负梯度不同。
2.GBDT回归算法
输入样本集 $ D=\left \{ (x,y_{1}),(x_{2},y_{2}),...(x_{m},y_{m}) \right \} $ ,最大迭代次数 $ T $ ,损失函数 $ L $
输出为强学习器器 $ f(x) $
1)初始化弱学习器
$$
\begin{align}
f_{0}(x)=\underset{c}{\underbrace{argmin}}\sum_{i=1}^{m}{L(y_{i},c)}\nonumber
\end{align}
$$2)对迭代轮数 $ t=1,2,3,\cdots ,T $ 有:
a)对样本 $ i=1,2,3,\cdots ,m $ 计算负梯度
$$
\begin{align}
r_{ti}=-\left [ \frac{\partial L(y_{i},f(x_{i}))}{\partial f(x_{i})} \right ]_{f(x)=f_{t-1}(x)}\nonumber
\end{align}
$$b)利用$ (x_{i},r_{ti})(i=1,2,3\cdots ,m) $ ,拟合一棵CART回归树,得到第 $ t $ 棵回归树,其对应的叶子节点区域为 $ R_{tj},j=1,2,3,\cdots ,J $ 。其中 $ J $ 为叶子节点的个数。
c)对叶子区域 $j=1,2,3,\cdots ,J $ 计算最佳的拟合值
$$
\begin{align}
c_{tj}=\underset{c}{\underbrace{argmin}}\sum_{x_{i}\in R_{tj}}{L(y_{i},f_{t-1}(x_{i})+c)}\nonumber
\end{align}
$$d)更新强学习器
$$
\begin{align}
f_{t}(x)=f_{t-1}(x)+\sum_{j=1}^{J}c_{tj}I(x\in R_{tj})\nonumber
\end{align}
$$3)得到强学习器 $ f(x) $ 的表达式:
$$
\begin{align}
f(x)=f_{T}(x)=f_{0}(x)+\sum_{t=1}^{T}\sum_{j=1}^{J}c_{tj}I(x\in R_{tj})\nonumber
\end{align}
$$
3.GBDT分类算法
GBDT分类算法从思想上和GBDT的回归算法没有区别,但是由于输出不是连续的值,而是离散的类别,导致无法直接从输出的类别去拟合类别输出的误差。
为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT就变为AdaBoost算法。另一种是用类似于逻辑回归的对数似然损失函数的方法。
对于二元GBDT,若用类似逻辑回归的对数似然损失函数,则损失函数为:
$$
\begin{align}
L(y,f(x))=log(1+exp(-yf(x)))\nonumber
\end{align}
$$
其中 $ y\in \left \{ -1, 1 \right \} $ 。则此时的负梯度误差为:
$$
\begin{align}
r_{ti}=-\left [ \frac{\partial L(y_{i},f(x_{i}))}{\partial f(x_{i})} \right ]_{f(x)=f_{t-1}(x)}=y_{i}/(1+exp(y_{i}f(x_{i})))\nonumber
\end{align}
$$
对于生成的决策树,各个叶子节点的最佳负梯度拟合值为:
$$
\begin{align}
c_{tj}=\underset{c}{\underbrace{argmin}}\sum_{x_{i}\in R_{tj}}{log(1+exp(-y_{i}(f_{t-1}(x_{i})+c)))}\nonumber
\end{align}
$$
由于上式优化比较困难,一般采用近似值代替:
$$
\begin{align}
c_{tj}=\frac{\sum_{x_{i}\in R_{tj}}{r_{ti}}}{\sum_{x_{i}\in R_{tj}}{\left | r_{tj} \right |}(1-\left | r_{tj} \right |)}\nonumber
\end{align}
$$
GBDT主要的优点有:
1) 可以灵活处理各种类型的数据,包括连续值和离散值。
2) 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
3) 使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。
GBDT的主要缺点有:
1) 由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。
·XGBoost
XGBoost算法是对GBDT算法的优化与升级。相对于GBDT,XGBoost主要进行的优化之处主要在一下几个方面:
算法本身的优化:在算法的弱学习器模型的选择上,GBDT算法模型支持决策树,XGBoost算法模型除了支持决策树外,还可以支持其他的弱学习器。在算法的损失函数上,XGBoost除了本身的损失函数之外,还加入了正则项。在对算法的优化方面,GBDT的损失函数只对误差部分做负梯度(一阶泰勒)展开,XGBoost的损失函数则对误差部分做了二阶泰勒展开,使得结果更加的准确率。
2.算法运行效率的优化:对于每一个弱学习器,如决策树建立的过程做并行选择,找到合适的子树分裂特征和特征值。在并行选择前,先对所有的特征的值进行排序分组,便于并行特征选择。对分组的特征,选择合适的分组大小,使用CPU缓存进行读取加速。将各个分组保存到多个硬盘以提高IO速度。
3.算法健壮性的优化:对于缺失值的特征,通过枚举所有缺失值在当前节点是进入左子树还是右子树决定缺失值的处理方式。算法本身加入了L1和L2正则化项,可以防止过拟合,泛化能力更强。
1.XGBoost损失函数
对于XGBoost算法来说,希望将GBDT算法流程的第2步和第3步合并在一起操作,即一次求解出决策树最优的所有 $ J $ 个叶子节点区域和每个叶子节点区域的最优解 $ c_{tj} $ 。XGBoost的损失函数在GBDT损失函数 $ L(y,f_{t-1}(x)+h_{t}(x)) $ 的基础上加入了正则化项,正则化项如下:
$$
\begin{align}
\Omega (h_{t})=\gamma J+\frac{\lambda }{2}\sum_{j=1}^{J}w_{tj}^{2}\nonumber
\end{align}
$$
这里的 $ J $ 是叶子节点的个数, $ w_{tj}^{2} $ 是第 $ j $ 个叶子节点的最优值。 $ w_{tj} $ 和GBDT中使用的 $ c_{tj} $ 是相同的意思。
最终的XGBoost的损失函数表示为:
$$
\begin{align}
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}\nonumber
\end{align}
$$
最终需要优化上式的损失函数,得到第 $ t $ 棵决策树最优的所有 $ J $ 个叶子节点区域和每个叶子节点区域的最优解 $ w_{tj} $ 。XGBoost不是像GBDT一样去拟合泰勒展开式的一阶导数,而是期望直接基于损失函数的二阶泰勒展开式进行求解。XGBoost损失函数的二阶泰勒展开式如下:
$$
\begin{align}
L_{t}\nonumber\nonumber
&=\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}\nonumber\\
&\approx \sum_{i=1}^{m}(L(y_{i},f_{t-1}(x_{i}))+\frac{\partial L(y_{i},f_{t-1}(x_{i}))}{\partial f_{t-1}(x_{i})}h_{t}(x_{i})+\frac{1}{2}\frac{\partial ^{2}L(y_{i},f_{t-1}(x_{i}))}{\partial f_{t-1}^{2}(x_{i})}h_{t}^{2}(x_{i}))+\gamma J+\frac{\lambda }{2}\sum_{j=1}^{J}w_{tj}^{2}\nonumber
\end{align}
$$
假设第 $ i $ 个样本在第 $ t $ 个弱学习器的一阶和二阶导数分别记为:
$$
\begin{align}
g_{ti}=\frac{\partial L(y_{i},f_{t-1}(x_{i}))}{\partial f_{t-1}(x_{i})},h_{ti}=\frac{\partial ^{2}L(y_{i},f_{t-1}(x_{i}))}{\partial f_{t-1}^{2}(x_{i})}\nonumber
\end{align}
$$
则损失函数的二阶泰勒展开式可以表示为:
$$
\begin{align}
L_{t}\nonumber
&\approx \sum_{i=1}^{m}(L(y_{i},f_{t-1}(x_{i}))+g_{ti}h_{t}(x_{i})+\frac{1}{2}h_{ti}h_{t}^{2}(x_{i}))+\gamma J+\frac{\lambda }{2}\sum_{j=1}^{J}w_{tj}^{2}\nonumber
\end{align}
$$
损失函数里的 $ L(y_{i}, f_{t-1}(x_{i})) $ 是常数,对最小化无影响,可以直接去掉。同时由于每个决策树的第 $ j $ 个叶子节点的取值最终会是,同一个值 $ w_{tj} $ ,因此损失函数可以简化为:
$$
\begin{align}
L_{t}\nonumber
&\approx \sum_{i=1}^{m}g_{ti}h_{t}(x_{i})+\frac{1}{2}h_{ti}h_{t}^{2}(x_{i})+\gamma J+\frac{\lambda }{2}\sum_{j=1}^{J}w_{tj}^{2}\nonumber\\
& = \sum_{j=1}^{J}(\sum_{x_{i}\in R_{tj}}g_{ti}w_{tj}+\frac{1}{2}\sum_{x_{i}\in R_{tj}}h_{ti}w_{tj}^{2})+\gamma J+\frac{\lambda }{2}\sum_{j=1}^{J}w_{tj}^{2}\nonumber\\
& = \sum_{j=1}^{J}[(\sum_{x_{i}\in R_{tj}}g_{ti})w_{tj}+\frac{1}{2}(\sum_{x_{i}\in R_{tj}}h_{ti}+\lambda )w_{tj}^{2}]+\gamma J\nonumber
\end{align}
$$
将每个叶子节点区域样本的一阶导数和二阶导数的和单独表示如下:
$$
\begin{align}
G_{tj}=\sum_{x_{i}\in R_{tj}}g_{ti},H_{tj}=\sum_{x_{i}\in R_{tj}}h_{ti})\nonumber
\end{align}
$$
损失函数最终表示为:
$$
\begin{align}
L_{t}=\sum_{j=1}^{J}[G_{tj}w_{tj}+\frac{1}{2}(H_{tj}+\lambda )w_{tj}^{2}]+\gamma J\nonumber
\end{align}
$$
对于如何解决一次求出决策树最优的所有 $ J $ 个叶子节点区域和每个叶子节点区域的最优解 $ w_{tj} $ ,可以将问题差分为两个问题:
1)如果已经求出了第 $ t $ 棵决策树的 $ J $ 个叶子节点区域,如何求出每个叶子节点区域的最优解 $ w_{tj} $ ?
2)对当前决策树做子树分裂时,应该如何选择哪个特征和特征值进行分裂,是最终的损失函数 $ L_{t} $ 最小?
对于第一个问题,直接基于损失函数对 $ w_{tj} $ 求导,并令导数为0即可。求解出的叶子节点区域的最优解 $ w_{tj} $ 的表达式为:
$$
\begin{align}
w_{tj}=-\frac{G_{tj}}{H_{tj}+\lambda }\nonumber
\end{align}
$$
对于第二个问题,在GBDT里时直接拟合的CART决策树,所以树节点分裂使用的时均方误差。XGBoost不是使用均方误差,而是使用贪心法,即每次分裂都期望最小化损失函数的误差。
当 $ w_{tj} $ 取最优值时,原损失函数表示为:
$$
\begin{align}
L_{t}=-\frac{1}{2}\sum _{j=1}^{J}\frac{G_{tj}^{2}}{H_{tj}+\lambda +\gamma J}\nonumber
\end{align}
$$
如果每次做左右子树分裂时,可以最大程度的减小损失函数就好了。也就是假设当前节点左右子树的一阶二阶导数和为 $ G_{L},H_{L},G_{R},H_{L} $ ,则期望最大化下式:
$$
\begin{align}
-\frac{1}{2}\frac{(G_{L}+G_{R})^{2}}{H_{L}+H_{R}+\lambda }+\gamma J-(-\frac{1}{2}\frac{G_{L}^{2}}{H_{L}+\lambda }-\frac{1}{2}\frac{G_{R}^{2}}{H_{R}+\lambda}+\gamma (J+1))\nonumber
\end{align}
$$
上式整理后可以转换为:
$$
\begin{align}
max\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\nonumber
\end{align}
$$
现在,决策树的分裂标准转换为上式。
举个简单的年龄特征的例子如下,假设我们选择年龄这个 特征的值a作为决策树的分裂标准,则可以得到左子树2个人,右子树三个人,这样可以分别计算出左右子树的一阶和二阶导数和,进而求出最终的上式的值。具体的分裂过程如下图所示:
然后我们使用其他的不是值a的划分标准,可以得到其他组合的一阶和二阶导数和,进而求出上式的值。最终我们找出可以使上式最大的组合,以它对应的特征值来分裂子树。
2.XGBoost算法主流程
输入:训练集样本 $ D=\left \{ (x,y_{1}),(x_{2},y_{2}),...(x_{m},y_{m}) \right \} $ ,最大迭代次数 $ T $ ,损失函数 $ L $ ,正则化系数 $ \lambda ,\gamma $
输出:强学习器 $ f(x) $
对迭代轮数 $ t=1,2, ,\cdots ,T$ 有:
1)计算第 $ i $ 个样本 $ (i-1, 2, \cdots,m) $ 在当前轮损失函数 $ L $ 基于 $ f_{t-1}(x_{i}) $ 的一阶导数 $ g_{ti} $ ,二阶导数 $ h_{ti} $ ,计算样本的一阶导数 $ G_{t}=\sum_{i=1}^{m}g_{ti} $ 和 二阶导数 $ H_{t}=\sum_{i=1}^{m}h_{ti} $
2)基于当前节点尝试分裂决策树,默认分数 $ score=0 $ , $ G, H $ 为当前需要分裂的节点的一阶和二阶之和。
对特征序号 $ k=1,2,\cdots,K: $
a) $ G_{L}=0,H_{L}=0 $
b.1) 将样本特征 $ k $ 从小到大排列,依次取出第 $ i $ 个样本,依次计算当前样本放入左子树后,左右子树一阶和二阶导数和:
$$
\begin{align}
G_{L}=G_{L}+g_{ti},G_{R}=G-G_{L}\nonumber\\
H_{L}=H_{L}+h_{ti},H_{R}=H-H_{L}\nonumber
\end{align}
$$b.2)尝试更新最大的分数:
$$
\begin{align}
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 )\nonumber
\end{align}
$$3)基于最大 $ score $ 对应的划分特征和特征值分裂子树。
4)如果最大 $ score=0 $ ,则当前据册数建立完毕,计算所有的叶子区域的 $ w_{tj} $ ,得到弱学习器 $ h_{t}(x) $ ,更新强学习器 $ f_{t}(x) $ ,进入下一轮弱学习器迭代。如果最大 $ score $ 不是 $ 0 $ ,则转到第2)步继续尝试分裂决策树。