这篇博客主要介绍一个最优化算法——前向分步算法,接着用前向分步算法推导 Adaboost 和提升树、梯度提升。
前向分步算法
前向分步算法是一种优化方法,给定损失函数 \(L\),预测函数 \(f(x)\),优化目标是最小化损失函数:
\[min\sum_{i=1}^{N}L(y_i, f(x_i))
\]
考虑一个预测函数,它由多个函数加权求和得到,这样的模型一般称之为加法模型。
\[f(x) = \sum_{m=1}^{M} \beta_m \, b(x;\gamma_m)
\]
前向分步算法,将函数拆分,每一步只计算一个函数加上去。下面的公式中,\(f_{m-1}\left( x \right)\) 是不变的,\(\beta \, b(x;\gamma)\) 是我们需要通过优化计算出来的。
\[f_m(x) = f_{m-1}\left( x \right) + \beta \, b(x;\gamma)
\]
在前向分步算法中,每一步损失函数都会降低。上一步的损失为:
\[\sum_{i=1}^{N}L(y_i, f_{m-1}\left( x_i \right))
\]
我们通过优化如下问题来降低损失:
\[\mathop{min}\limits_{\beta, \gamma} \sum_{i=1}^{N}L(y_i, f_{m-1}\left( x_i \right) + \beta \, b(x_i;\gamma))
\]
每一步都能保证不会使到损失增加。至于这个算法是否能找到最优的加权组合,我觉得不一定可以,就像坐标下降一样。目前对它的理解还不够深刻,只能说它能够求解某个局部最优函数组合。
算法描述
Adaboost
加法模型,我们可以将其理解为弱学习器加权组合为强学习器。Adaboost 是一个 boosting 算法,将弱学习器转为强学习器。在 Adaboost 中,我们有目标函数:
\[f(x) = \sum_{m=1}^{M} \alpha_m \, G_m(x)
\]
Adaboost 的损失函数为指数函数:
\[L(y, f(x)) = e^{-y \, f(x)}
\]
\[y = f(x), L = e^{-1}
\]
\[y \ne f(x), L = e^{1}
\]
这样的损失函数是合理的,因为预测正确时的损失小于预测错误时的损失。
使用前向分步算法,我们可以开始推理了。
第一步,设置
\[f_0\left( x \right) = 0
\]
第二步,
\[f_m(x) = f_{m-1}\left( x \right) + \alpha_m \, G_m(x)
\]
优化损失函数:
\[\sum_{i=1}^{N} exp[- (f_{m-1}\left( x_i \right) + \alpha_m \, G_m(x_i)) y_i]
\]
\[\sum_{i=1}^{N} exp[- y_i \, f_{m-1} \left( x_i \right)] \; exp[- y_i \alpha_m G_m(x_i) ]
\]
对每个 \(x_i\),在确定 \(f_{m-1}\) 的情况下,前半部分 \(exp[- y_i \, f_{m-1} \left( x_i \right)]\) 是固定的。
\[\overline{w}_{mi} = exp[- y_i \, f_{m-1} \left( x_i \right)]
\]
\[\sum_{i=1}^{N} \overline{w}_{mi} \; exp[- y_i \alpha_m G_m(x_i) ]
\]
第三步,固定 \(\alpha\),学习最优的 \(G_m(x)\) 使到损失函数最小化。
\[G_m(x) = arg \, \mathop{min}\limits_{G(x)} \sum_{i=1}^{N} \overline{w}_{mi} \, I(y_i = G(x_i))
\]
第四步,继续优化函数以求出 \(\alpha\)
\[\sum_{i=1}^{N} \overline{w}_{mi} \; exp[- y_i \alpha_m G_m(x_i) ]
\]
\[\mathop{\sum}\limits_{y_i \ne Gm(x_i)} \overline{w}_{mi} \; e^{\alpha} + \mathop{\sum}\limits_{y_i = Gm(x_i)} \overline{w}_{mi} \; e^{- \alpha}
\]
\[\sum_{i=1}^{N} \overline{w}_{mi} \; e^{-\alpha} + \sum_{i=1}^{N} \overline{w}_{mi} \; \left( e^{\alpha} - e^{-\alpha} \right) I\left( y_i \ne G_m(x_i) \right)
\]
对 \(\alpha\) 求导,并令等式为 \(0\),
\[-\sum_{i=1}^{N} \overline{w}_{mi} \; e^{-\alpha} + \sum_{i=1}^{N} \overline{w}_{mi} \; \left( e^{\alpha} + e^{-\alpha} \right) I\left( y_i \ne G_m(x_i) \right) = 0
\]
\[\sum_{i=1}^{N} \overline{w}_{mi} \; e^{-\alpha} = \sum_{i=1}^{N} \overline{w}_{mi} \; \left( e^{\alpha} + e^{-\alpha} \right) I\left( y_i \ne G_m(x_i) \right)
\]
\[e^{-\alpha} \sum_{i=1}^{N} \overline{w}_{mi} = \left( e^{\alpha} + e^{-\alpha} \right) \sum_{i=1}^{N} \overline{w}_{mi} \; I\left( y_i \ne G_m(x_i) \right)
\]
\[\frac{e^{-\alpha}}{\left( e^{\alpha} + e^{-\alpha} \right)} = \frac{\sum_{i=1}^{N} \overline{w}_{mi} \; I\left( y_i \ne G_m(x_i) \right)}{\sum_{i=1}^{N} \overline{w}_{mi}}
\]
等式右边为加权的错误率:
\[\frac{\sum_{i=1}^{N} \overline{w}_{mi} \; I\left( y_i \ne G_m(x_i) \right)}{\sum_{i=1}^{N} \overline{w}_{mi}} = \sum_{i=1}^{N} w_{mi} \; I\left( y_i \ne G_m(x_i) \right) = e_m
\]
代入:
\[\frac{e^{-\alpha}}{\left( e^{\alpha} + e^{-\alpha} \right)} = e_m
\]
\[\frac{1}{\left( e^{2\alpha} + 1 \right)} = e_m
\]
\[\alpha = \frac{1}{2} \log \frac{1-e_m}{e_m}
\]
第五步,计次。如果次数未达到 \(M\),回到第二步。
权值更新的公式推理:
我们可以递推得到 \(\overline{w}_{m+1, i}\),下一步的损失函数为:
\[\sum_{i=1}^{N} exp[- y_i (f_m(x_i) + \alpha_m \, G_m(x_i))]
\]
\[\sum_{i=1}^{N} exp[-y_i \, f_m(x_i)] \, exp[- y_i \, \alpha_m+1 \, G_m+1 \left( x_i \right)]
\]
\[\overline{w}_{m+1, i} = exp[-y_i \, f_m(x_i)] = exp[- y_i \, f_{m-1} \left( x_i \right)] \; exp[- y_i \alpha_m G_m(x_i) ] = \overline{w}_{m, i} \; exp[- y_i \alpha_m G_m(x_i) ]
\]
最后,我们在计算加权错误率的时候,是规范化了的,所以还要带上规范化因子。
提升树
提升树的算法思路可以这样表述:从原始数据中学习一个函数 \(f_1(x)\)。用这个函数去预测,将预测的结果和实际的结果做差,得到“残差”,\(r=y_i - f_1(x_i)\)。接着从残差学习一个函数 \(f_2(x)\),再预测,再计算残差。如此往复进行 \(M\) 次。最终的预测模型为加法模型,\(f(x) = \sum_{i=1}^{M} f_i(x)\)。
提升树模型中,使用的基学习器是决策树,不需要加权求和,使用的损失函数是平方损失函数。基于决策树的加法模型如下:
\[f(x) = \sum_{m=1}^{M} T_{m}(x)
\]
损失函数定义为:
\[L(y, f(x)) = \frac{1}{2} \; (y - f(x))^2
\]
加法模型定义为,
\[f_m(x) = f_{m-1} \left( x \right) + T_m(x)
\]
损失函数为:
\[\begin {split}
L(y, f_m(x)) &= L(y, f_{m-1} \left( x \right) + T_m(x)) \\
&= \frac{1}{2} (y_i - f_{m-1} \left( x \right) - T_m(x))^2 \\
&= \frac{1}{2} (r_{mi} - T_m(x))^2 \\
\end{split}
\]
于是,让 \(T_m(x)\) 去拟合残差,就可以使到损失函数最小。
算法描述:
最后还要对所有的决策树进行求和。
梯度提升(Gradient Boosting)
梯度提升类似梯度下降算法一样,只不过梯度下降算法是在实数空间上进行优化,而梯度提升是在函数空间上进行优化。链接 [2] 对比了两种梯度优化算法。
设加法模型为:
\[f_m(x) = f_{m-1} \left( x \right) + T_m(x)
\]
\[T_m(x) = f_m(x) - f_{m-1} \left( x \right)
\]
损失函数定义为:
\[L(y, f(x)) = L(y, f_{m-1} \left( x \right) + T_m(x))
\]
将损失函数进行展开:
\[L(y, f_m(x)) \approx L(y, f_{m-1} \left( x \right)) + \frac{\partial L(y, f_{m-1} \left( x \right))}{\partial f_{m-1} \left( x \right)} \; T_m(x)
\]
为了降低损失函数,可以使 \(T_m(x)\) 朝着负梯度的方向,也就是
\[T_m(x) = - \eta \, \frac{\partial L(y, f_{m-1} \left( x \right))}{\partial f_{m-1} \left( x \right)}
\]
因此,在使用梯度提升的时候,从原始数据中学习一个函数 \(f_1(x)\)。对损失函数计算偏导,求出负梯度。接着从负梯度学习一个函数 \(f_2(x)\),再预测,再计算负梯度。如此往复进行 \(M\) 次。最终的预测模型为加法模型,\(f(x) = \sum_{i=1}^{M} f_i(x)\)。
对于平方损失函数,我们可以证明每个基学习器要学习的是残差 \(y - f_{m-1} \left( x \right)\):
\[\begin {split}
T_m(x) &= -\frac{\partial L(y, f_{m-1} \left( x \right))}{\partial f_{m-1} \left( x \right)} \\
&= -\frac{\partial \frac{1}{2} \, (y - f_{m-1} \left( x \right))^2}{\partial f_{m-1} \left( x \right)} \\
&= -(y - f_{m-1} \left( x \right)) *(-1) \\
&= y - f_{m-1} \left( x \right) \\
\end {split}
\]
Q&A
Q: 在李航机器学习第一版中,第 151 页中提到,“利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中的残差近似值”,负梯度是残差的近似值吗?
A: 这个地方尚存有疑问。现在可以证明的是,对于平方损失函数,负梯度刚好就是残差。但是对于一般的损失函数,我怎么也想不明白,负梯度是如何近似残差的。查了一些资料,也没有看到。第二版还是继续保留了相关的论述,因此负梯度是残差的近似值这一说法应该有办法证明,需要再多尝试。
参考
[1] 李航机器学习
[2] https://www.zhihu.com/question/63560633/answer/581670747