参考网址:
2. Wikipedia: Gradient boosting
一般Gradient Boosting:
先用原函数值拟合一个模型,而后计算残差,再构建新的基(弱)学习器,不断重复,最后将这些基模型的结果加权相加,得到最后的结果。
输入:训练集$\{(x_{i}, y_{i})\}_{i=1}^{n}$,可导损失函数$L(y, F(x))$,迭代次数$M$
算法:
1. 用常数值初始化模型
\[F_{0}=\arg\underset{\gamma}{\min} \sum_{i=1}^{n} L(y_{i}, \gamma)\]
2. 从m=1到M:
1)计算“伪残差”:
\[ r_{im}=-[\frac{\partial L(y_{i}, F(x_{i}))}{\partial F(x_{i})}]|_{F(x)=F_{m-1}(x)},i=1, ..., n\]
当$L(y, F(x))$是$\frac{1}{2} (y-F(x))^{2})$时,$\frac{\partial L(y, F(x))}{\partial F(x)}=-(y-F(x))$,即为残差
2)拟合基学习器(如:树)$h_m(x)$,使用训练集为$\{(x_i, r_{im})\}_{i=1}^{n}$
3)通过一维优化问题计算乘子$\gamma_m$:
\[\gamma_m=\arg\underset{\gamma}{\min} \sum_{i=1}^{n} L(y_i, F_{m-1}(x_i)+\gamma h_m(x_i))\]
4)更新模型:
\[F_m(x)=F_{m-1}(x)+\gamma_mh_m(x)\]
3. 输出$F_m(x)$
注意,就算是两个同类基学习器的加权效果累加,也不一定能通过该类学习器单个实现。例如,如果是多项式为基学习器,那么能找到一个多项式实现另外两个多项式的任意加权叠加效果;但当基学习器为树的时候,两棵简单的树的效果叠加,也是不一定能通过另一棵树(无论层次多深)去实现的。这是这个算法会产生和原学习器不同效果的一个基础。
Gradient Tree Boosting(包括了Gradient boosting decision tree:GBDT)
Gradient Tree Boosting一般是用决策树(尤其是CART树)作为基学习器。树的大小一般是固定的。对于这特定的以树作为基学习器的情形,Friedman作了一些修正来提升它的效果。
主要体现在第2点,在第m步迭代时,用决策树$h_m(x)$拟合伪残差。
记$J_m$为该树的叶子结点数目,则输入空间被划分为$J_m$个不相交的区域:$R_{1m},R_{2m}, ..., R_{J_{m} m}$。每个区域的预测值为一个常数,记为$b_{jm}$。
则\[h_m(x)=\sum_{j=1}^{J_m}b_{jm}1_{R_{jm}} (x).\]
$1_{R_{jm}}$为示性函数。
如果是原本的Gradient boosting算法,系数$b_{jm}$和$\gamma_m$相乘,并通过用线性搜索的方法对loss function求小值解来确定这些系数。模型更新的步骤如下:
\[F_m(x)=F_{m-1}(x)+\gamma_m h_m(x), \gamma_m=\arg\underset{\gamma}{\min} \sum_{i=1}^{n}L(y_i, F_{m-1}(x_i)+\gamma h_m(x_i))\]
Friedman提出的修正方法是为树的每一个区域$\{R_{jm}\}_1^{J_m}$都选择一个最优的$\gamma_{jm}$,而不是整棵树只用一个$\gamma_m$。
Friedman称修正后的算法为"TreeBoost“。通过这样的方式,实际上$b_{jm}$可以直接移除,模型更新变为:
\[F_m(x)=F_{m-1}(x)+\sum_{j=1}^{J_m}\gamma_{jm} 1_{R_{jm}}(x)\]
\[\gamma_{jm}=\arg\underset{\gamma}{\min} \sum_{x_i\in R_{jm}}L(y_i,F_{m-1}(x_i)+\gamma)\]
记J为树的叶子节点个数,可以根据数据集做调整,它控制的是模型中不同变量的交互作用(interaction)。
例如当J=2时,变量间不存在交互作用,而如果J=3,则至多有两个变量之间存在交互作用。
Hastie等人认为一般$4\leq J \leq8$对于boosting来说效果较好,并且当$J$处于这个范围的时候,效果受$J$变化的影响不敏感。$J=2$在多数应用场景都不太够,而一般也不需要用到$J=10$的情形。
Regularization:正则化减小过拟合风险
如果模型太贴合训练集,可能会导致模型的泛化能力变差。
有几种正则化方法可以减少过拟合的发生可能。
控制迭代次数M(例如GBDT中的树的棵树)是其中一种十分自然的想法。M增大时训练误差减小,但过大时就会导致过拟合发生。最优的M通常是通过控制独立的验证集的预测误差来确定的。
其他的方法如下:
1. Shrinkage收缩 :引入学习率learning rate
\[F_m(x)=F_{m-1}(x)+v\cdot \gamma_mh_m(x),0\leq v\leq1\]
v称为学习率。在学习率低时(例如$v<0.1$),相比于没有收缩(即v=1)时,模型泛化能力会有显著提高,但由于迭代次数会增加,也造成了计算时间变长.
2.Stochastic gradient boosting随机梯度提升
受Breiman的启发,Friedman在Gradient boosting提出来后不久就提出了一个小的修改方案:每一次迭代构建基学习器时,不用所有的训练集样本,而用其子集。这种改进的效果提升很明显。
在每次构建时,子集的占比(子集样本数/训练集样本总数)$f$是确定的,当$f=1$时,就是原来的算法。$f$设置得小时,是把随机性引入到模型当中,有助于减轻过拟合的现象。而由于每次迭代计算时计算需要的样本数减小了,模型训练的速度也得到提升。
$f$一般设为0.5(也就是每次建树用了一半的训练样本),Friedman认为$0.5\leq f \leq0.8$对于中小型数据集的效果都不错。
在这种改进的算法里,有一种out-of-bag的误差会被计算(out-of-bag error),我理解里,指的是用没有在下一个基学习器里训练用到的样本,去计算这个(指前面的"下一个“)的预测误差,衡量其预测效果。但和用验证集相比,这种估计会低估实际的效果提升,以及最优的迭代次数。
3.Number of observations in the tree
限制每棵树叶子节点最小的样本数,这可以降低预测值的方差。
4. Penalized complexity of Tree
对模型复杂度进行惩罚。模型复杂度可以定义为叶子数的某个比例。
损失函数和模型复杂度的联合优化对应着,在一定阈值限定内,减小损失函数的后剪枝算法。另外,对叶子节点加上$l2$惩罚项,也可以避免过拟合。 ℓ 2 {\displaystyle \ell _{2}} penalty on the leaf values can also be added to avoid overfitting.
Multiple Additive Regression Trees" (MART)也是指的这个算法。