LESSON 12.8 原理进阶 (1):GBDT数学流程与残差概念辨析
四 原理进阶:GBDT的求解流程
1 GBDT的基本数学流程
作为当代众多经典算法的基础,GBDT的求解过程可谓十分精妙,它不仅开创性地舍弃了使用原始标签进行训练的方式,同时还极大地简化了Boosting算法的运算流程,让Boosting算法本该非常复杂的运算流程变得清晰简洁。当我们学过完整的AdaBoost流程后,我们会发现GBDT的数学流程非常简明、美丽,同时这一美丽的流程也是我们未来所有Boosting高级算法的数学基础。与任意Boosting算法一致,对GBDT我们需要回答如下问题:
- 损失函数L(x,y)L(x,y)L(x,y)的表达式是什么?损失函数如何影响模型构建?
- 弱评估器f(x)f(x)f(x) 是什么,当下boosting算法使用的具体建树过程是什么?
- 综合集成结果H(x)H(x)H(x)是什么?集成算法具体如何输出集成结果?
同时,还可能存在其他需要明确的问题,例如:
- 是加权求和吗?如果是,加权求和中的权重如何求解?
- 训练过程中,拟合的数据XXX与yyy分别是什么?
- 模型训练到什么时候停下来最好?
对于GBDT,由于我们存在提前停止机制以及资源控制,因此我们一般不去在意模型停止相关的问题,但除此之外的每个问题我们都需要仔细研究。
回顾Boosting算法的基本指导思想,我们来梳理梯度提升树回归算法的基本流程。虽然Boosting理论很早就被人提出,但1999年才是GBDT算法发展的高潮。1999年,有四篇论文横空出世:
《贪心函数估计:一种梯度提升机器》
Friedman, J. H. (February 1999). “Greedy Function Approximation: A Gradient Boosting Machine”
《随机梯度提升》
Friedman, J. H. (March 1999). “Stochastic Gradient Boosting”
《梯度下降式提升算法》
Mason, L.; Baxter, J.; Bartlett, P. L.; Frean, Marcus (1999). “Boosting Algorithms as Gradient Descent”
《函数空间中的梯度下降式提升算法》
Mason, L.; Baxter, J.; Bartlett, P. L.; Frean, Marcus (May 1999). “Boosting Algorithms as Gradient Descent in Function Space”
今天我们学习的GBDT算法是融合了上述4篇论文思想的集大成之作。本次我们将基于sklearn中实现的GBDT来梳理数学流程,但不同的数学流程可能来自于上述不同的论文。需要注意的是,为了与之前课程中的符号表达相一致,我们将使用与原论文不同的符号,但数学过程将是完全相同的。
假设现有数据集NNN,含有形如(xi,yi)(x_i,y_i)(xi,yi)的样本MMM个,iii为任意样本的编号,单一样本的损失函数为l(yi,H(xi))l(y_i,H(x_i))l(yi,H(xi)),其中H(xi)H(x_i)H(xi)是iii号样本在集成算法上的预测结果,整个算法的损失函数为L(y,H(x))L(y,H(x))L(y,H(x)),且总损失等于全部样本的损失之和:L(y,H(x))=∑il(yi,H(xi))L(y,H(x)) = \sum_il(y_i,H(x_i))L(y,H(x))=∑il(yi,H(xi))。同时,弱评估器为回归树fff,总共学习TTT轮。则GBDT回归的基本流程如下所示:
1)初始化数据迭代的起点H0(x)H_0(x)H0(x)。sklearn当中,我们可以使用0、随机数或者任意算法的输出结果作为H0(x)H_0(x)H0(x),但在最初的论文中,Friedman定义了如下公式来计算H0H_0H0:
H0(x)=argminC∑i=1Ml(yi,C)=argminCL(y,C)\begin{aligned} H_{0}(x) &=\underset{C}{\operatorname{argmin}} \sum_{i=1}^{M} l\left(y_{i}, C\right) \\ &=\underset{C}{\operatorname{argmin}} L(y, C) \end{aligned} H0(x)=Cargmini=1∑Ml(yi,C)=CargminL(y,C)
其中yiy_iyi为真实标签,CCC为任意常数。以上式子表示,找出令∑i=1Ml(yi,C)\sum_{i=1}^Ml(y_i,C)∑i=1Ml(yi,C)最小的常数CCC值,并输出最小的∑i=1Ml(yi,C)\sum_{i=1}^Ml(y_i,C)∑i=1Ml(yi,C)作为H0(x)H_0(x)H0(x)的值。需要注意的是,由于H0(x)H_0(x)H0(x)是由全部样本的lll计算出来的,因此所有样本的初始值都是H0(x)H_0(x)H0(x),不存在针对某一样本的单一初始值。
开始循环,for t in 1,2,3…T:
- 在现有数据集NNN中,抽样MMM *
subsample
个样本,构成训练集NtN^tNt- 对任意一个样本iii,计算伪残差(pseudo-residuals)ritr_{it}rit,具体公式为:
rit=−∂l(yi,Ht−1(xi))∂Ht−1(xi)r_{it} = -\frac{\partial{l(y_i,H_{t-1}(x_i))}}{\partial{H_{t-1}(x_i)}}rit=−∂Ht−1(xi)∂l(yi,Ht−1(xi))
不难发现,伪残差是一个样本的损失函数对该样本在集成算法上的预测值求导后取负的结果,并且在进行第t次迭代、计算第t个伪残差时,我们使用的前t-1次迭代后输出的集成算法结果。在t=1时,所有伪残差计算中的Ht−1(xi)H_{t-1}(x_i)Ht−1(xi)都等于初始H0(x)H_0(x)H0(x),在t>0时,每个样本上的Ht−1(xi)H_{t-1}(x_i)Ht−1(xi)都是不同的取值。- 求解出伪残差后,在数据集(xi,rit)(x_i, r_{it})(xi,rit)上按照CART树规则建立一棵回归树ftf_tft,训练时拟合的标签为样本的伪残差ritr_{it}rit。
- 将数据集NtN_tNt上所有的样本输入ftf_tft进行预测,对每一个样本,得出预测结果ft(xi)f_t(x_i)ft(xi)。在数学上我们可以证明,只要拟合对象是伪残差ritr_{it}rit,则ft(xi)f_t(x_i)ft(xi)的值一定能让损失函数最快减小。
- 根据预测结果ft(xi)f_t(x_i)ft(xi)迭代模型,具体来说:
Ht(xi)=Ht−1(xi)+ft(xi)H_t(x_i) = H_{t-1}(x_i) + f_t(x_i)Ht(xi)=Ht−1(xi)+ft(xi)
假设输入的步长为η\etaη,则Ht(x)H_t(x)Ht(x)应该为:
Ht(xi)=Ht−1(xi)+ηft(xi)H_t(x_i) = H_{t-1}(x_i) + \eta f_t(x_i)Ht(xi)=Ht−1(xi)+ηft(xi)
对整个算法则有:
Ht(x)=Ht−1(x)+ηft(x)H_t(x) = H_{t-1}(x) + \eta f_t(x)Ht(x)=Ht−1(x)+ηft(x)
- 循环结束,输出HT(x)H_T(x)HT(x)的值作为集成模型的输出值。
以上就是GBDT完整的数学流程,不难发现,这个流程是比AdaBoost的流程更简洁的。当然,整体流程当中可能有不少令人困惑的地方,我们来一一解明:
2 初始化H0H_0H0过程中的常数C是什么?
在最初的论文中,Friedman定义了如下公式来计算H0H_0H0:
H0(x)=argminC∑i=1Ml(yi,C)H_{0}(x)=\underset{C}{\operatorname{argmin}} \sum_{i=1}^{M} l\left(y_{i}, C\right) H0(x)=Cargmini=1∑Ml(yi,C)=argminCL(yi,C)=\underset{C}{\operatorname{argmin}} L\left(y_{i}, C\right) =CargminL(yi,C)
其中yiy_iyi为真实标签,CCC为任意常数。以上式子表示,找出令整体损失L(yi,C)L(y_i,C)L(yi,C)最小的常数CCC值,并输出最小的L(yi,C)L(y_i,C)L(yi,C)作为H0(x)H_0(x)H0(x)的值。在刚观察这个式子时,大家可能很难理解CCC这个常数的作用,但这个式子实际上很简单——
首先,lll是损失函数,损失函数衡量两个自变量之间的差异,因此l(yi,C)l(y_i,C)l(yi,C)衡量样本iii的真实标签yiy_iyi与常数C之间的差异,因此L(yi,C)L(y_i,C)L(yi,C)是所有样本的真实标签与常数C之间的差异之和。现在我们要找到一个常数C,令所有样本的真实标签与常数C的差异之和最小,请问常数C是多少呢?这是一个典型的求极值问题,只需要对∑i=1Ml(yi,C)\sum_{i=1}^M l(y_i,C)∑i=1Ml(yi,C)求导,再令导数为0就可以解出令∑i=1Ml(yi,C)\sum_{i=1}^M l(y_i,C)∑i=1Ml(yi,C)最佳的C。假设lll是squared_error,每个样本的平方误差,则有:
∑i=1Ml(yi,C)=∑i=1M(yi−C)2\sum_{i=1}^M l(y_i,C) = \sum^M_{i=1}(y_i - C)^2i=1∑Ml(yi,C)=i=1∑M(yi−C)2
对上述式子求导,并令一阶导数等于0:
∂∂C∑i=1Ml(yi,C)=∂∂C∑i=1M(yi−C)2=∑i=1M−2(yi−C)=−2∑i=1Myi+2MC=0\begin{aligned} \frac{\partial}{\partial C} \sum_{i=1}^{M} l\left(y_{i}, C\right) &=\frac{\partial}{\partial C} \sum_{i=1}^{M}\left(y_{i}-C\right)^{2} \\ &=\sum_{i=1}^{M}-2\left(y_{i}-C\right) \\ &=-2 \sum_{i=1}^{M} y_{i}+2 M C \\ &=0 \end{aligned}∂C∂i=1∑Ml(yi,C)=∂C∂i=1∑M(yi−C)2=i=1∑M−2(yi−C)=−2i=1∑Myi+2MC=0
所以:
2∑i=1Myi=2MCC=1M∑i=1MyiC=mean(yi)\begin{aligned} 2 \sum_{i=1}^{M} y_{i} &=2 M C \\ C &=\frac{1}{M} \sum_{i=1}^{M} y_{i} \\ C &=\operatorname{mean}\left(y_{i}\right) \end{aligned} 2i=1∑MyiCC=2MC=M1i=1∑Myi=mean(yi)
可知,当L是平方误差squared error时,令L(yi,C)L(y_i,C)L(yi,C)最小的常数C就是真实标签的均值,这个过程与我们在学习Kmeans时证明各点到质心(均值)的距离就是最小SSE完全一致。因此,式子H0=argminC∑i=1Ml(yi,C)H_0 = \mathop{argmin}_{C} \sum_{i=1}^M l(y_i,C)H0=argminC∑i=1Ml(yi,C)的本质其实是求解C=mean(yi)C = mean(y_i)C=mean(yi)时的损失函数,并以此损失函数作为H0H_0H0的值。当然,如果我们选择了其他的损失函数,我们就需要以其他方式(甚至梯度下降)进行求解,CCC的值可能也就不再是均值了。
3 伪残差与残差、梯度有什么关系?
在讲解GBDT与AdaBoost之间的差异时,我们曾提到,AdaBoost是拟合原始数据XXX与真实标签yiy_iyi,而GBDT拟合的是原始数据XXX与残差(yi−H(xi))(y_i - H(x_i))(yi−H(xi)),但在上述数学流程中,我们拟合的对象伪残差既不像真实标签,也不像H(x)H(x)H(x)与yiy_iyi的差异,它到底是什么呢?
rit=−∂l(yi,Ht−1(xi))∂Ht−1(xi)r_{it} = -\frac{\partial{l(y_i,H_{t-1}(x_i))}}{\partial{H_{t-1}(x_i)}}rit=−∂Ht−1(xi)∂l(yi,Ht−1(xi))
从数学上来看,伪残差是一个样本的损失函数对该样本在集成算法上的预测值求导后取负的结果。假设现在损失函数是平方误差Squared error,则该求导过程很明显就是:
l=(yi−Ht−1(xi))2∂l∂Ht−1(xi)=∂∂Ht−1(xi)(yi−Ht−1(xi))2∂l∂Ht−1(xi)=−2(yi−Ht−1(xi))−∂l∂Ht−1(xi)=2(yi−Ht−1(xi))\begin{aligned} l &=\left(y_{i}-H_{t-1}\left(x_{i}\right)\right)^{2} \\ \frac{\partial l}{\partial H_{t-1}\left(x_{i}\right)} &=\frac{\partial}{\partial H_{t-1}\left(x_{i}\right)}\left(y_{i}-H_{t-1}\left(x_{i}\right)\right)^{2} \\ \frac{\partial l}{\partial H_{t-1}\left(x_{i}\right)} &=-2\left(y_{i}-H_{t-1}\left(x_{i}\right)\right) \\ -\frac{\partial l}{\partial H_{t-1}\left(x_{i}\right)} &=2\left(y_{i}-H_{t-1}\left(x_{i}\right)\right) \end{aligned}l∂Ht−1(xi)∂l∂Ht−1(xi)∂l−∂Ht−1(xi)∂l=(yi−Ht−1(xi))2=∂Ht−1(xi)∂(yi−Ht−1(xi))2=−2(yi−Ht−1(xi))=2(yi−Ht−1(xi))
不难发现,虽然伪残差看着与残差完全不相关,但其本质与残差非常相似。它是残差的某种变形,它的值不完全等同于残差的值,但是它衡量的差异与残差衡量的差异完全一致。因此,我可以让新建立的弱评估器拟合伪残差,这样算法就会更多地学习当下Ht(xi)H_t(x_i)Ht(xi)与yiy_iyi之间的差异,新建立的弱评估器预测出的结果也更有可能抹平这种差异。从直觉上来说,Ht(xi)H_t(x_i)Ht(xi)与yiy_iyi之间的差异越小,整体损失函数值就会越小,因此GBDT拟合伪残差是在向着损失函数最小化(偏差最小化)的方向拟合。
除此之外,伪残差是损失函数求导后取负的结果。一个函数对自变量求导后得到的结果称为梯度,代表字母为ggg,因此伪残差也被称为负梯度,也因此,GBDT被称为“拟合负梯度”的算法。这一说法拓展开来,我们可以说GBDT拟合负梯度、拟合伪残差、拟合损失函数在预测标签上的负导数。无论这些说法如何变化,其实指的都是同一个数学过程。不过,在最初的梯度提升机器(Gradient Boosting Machine)中,拟合的的确是残差y−H(x)y-H(x)y−H(x),只不过在后来改进的梯度提升树中,拟合残差过程被修改为拟合伪残差了。
需要注意的是,由于伪残差/负梯度都是针对单一样本计算的,所以一般在数学公式当中,梯度会被表示为gig_igi,其中iii为样本量。对GBDT来说则有:
ri=−gir_i = -g_iri=−gi
4 证明:拟合伪残差可以令损失函数最快地减小
从直觉上来看,拟合伪残差可以降低Ht(xi)H_t(x_i)Ht(xi)与yiy_iyi之间的差异,从而降低整体损失函数的值,但这个行为在数学上真的可行吗?毕竟,GBDT可以使用任意可微函数作为损失函数,不同损失函数求导后的结果即便与残差相似,也未必能代替真正的残差的效果。因此,不仅在直觉上需要理解拟合伪残差的作用,我们还需要从数学上证明:只要拟合对象是伪残差ritr_{it}rit,则弱评估器的输出值ft(xi)f_t(x_i)ft(xi)一定是让损失函数减小最快的值。
- 直观类比
假设现在有包含MMM个样本的数据集NtN^tNt,无论我们以什么规则建立新的弱评估器ftf_tft,我们一定是希望ftf_tft满足以下条件的:
ft=argminfL(yi,Ht(x))=argminf∑i=1Ml(yi,Ht−1(xi)+ft(xi))\begin{aligned} f_{t} &=\underset{f}{\operatorname{argmin}} L\left(y_{i}, H_{t}(x)\right) \\ &=\underset{f}{\operatorname{argmin}} \sum_{i=1}^{M} l\left(y_{i}, H_{t-1}\left(x_{i}\right)+f_{t}\left(x_{i}\right)\right) \end{aligned} ft=fargminL(yi,Ht(x))=fargmini=1∑Ml(yi,Ht−1(xi)+ft(xi))
上式表示,本轮弱评估器的输出值ftf_tft应该是令整体损失LLL最小化的ftf_tft。即,无论弱评估器ftf_tft是什么结构、什么规则、如何建立、如何拟合,其最终的输出值ft(xi)f_t(x_i)ft(xi)必须是令整体损失函数LLL最小化的ft(xi)f_t(x_i)ft(xi)。如果我们能保证这个条件成立,那随着算法逐步迭代,损失函数必然是会越来越小的。那我们如何保证这一点成立呢?在这里,我们需要使用论文《梯度下降式提升算法》中所提到的函数式梯度下降了——我们可以直接对整体损失函数进行梯度下降,找出当前最小值以及最小值对应的ft(xi)f_t(x_i)ft(xi)。
具体来说,回忆我们在逻辑回归中执行的梯度下降过程,当时我们的损失函数为L(w)L(\boldsymbol{w})L(w),其中www是逻辑回归的系数向量,且迭代www的方法如下:
wt=wt−1−ηgtw_{t} = w_{t-1} - \eta g_twt=wt−1−ηgt
公式中η\etaη为学习率,gtg_tgt为第ttt次迭代中的梯度向量,包含了全部www的梯度[g1,g2,g3...gn][g_1,g_2,g_3...g_n][g1,g2,g3...gn]。通过在www上直接增加学习率*负梯度,我们可以保证损失函数L(w)L(\boldsymbol{w})L(w)在www迭代过程中一定是越来越小的,因为在学习梯度下降时我们证明过,负梯度的方向就是损失函数下降最快的方向。那相同的思路也可以被用到GBDT当中。
在GBDT中,我们的损失函数为L(yi,Ht(x))L(y_i, H_t(x))L(yi,Ht(x)),并且我们的Ht(x)H_t(x)Ht(x)是按以下方式迭代的:
Ht(x)=Ht−1(x)+ηft(x)H_t(x) = H_{t-1}(x) + \eta f_t(x)Ht(x)=Ht−1(x)+ηft(x)
其中Ht(x)H_t(x)Ht(x)是,第ttt次迭代中全部样本在算法上的输出值,ft(x)f_t(x)ft(x)则是第ttt次迭代中全部样本在新弱评估器上输出的ft(xi)f_t(x_i)ft(xi)。原则上来说,对标传统梯度下降,只要让ft(x)=−gtf_t(x) = -g_tft(x)=−gt,即让ft(xi)=−gif_t(x_i) = -g_ift(xi)=−gi,就一定能够保证损失函数L(yi,Ht(x))L(y_i,H_t(x))L(yi,Ht(x))是随迭代下降的。
当我们已经知道能够令损失函数最小的ft(xi)f_t(x_i)ft(xi)就是−gi-g_i−gi之后,如何逼迫新建立的弱评估器输出−gi-g_i−gi这个数字呢?答案是,让新建立的弱评估器拟合(xix_ixi,−gi-g_i−gi)。所以你现在应该已经猜到了,每个样本的伪残差rir_iri(负梯度−gi-g_i−gi)其实就是能够令损失函数减小最快的ft(xi)f_t(x_i)ft(xi)的值。
- 严谨证明
当然,上述过程只是类比,并非严谨的数学证明。如果我们想要证明负梯度就是让损失函数减小最快的值,则需要借助泰勒级数来帮助我们。
在数学中,泰勒级数使用无限个项的连加式来表示一个函数。实际应用当中,我们一般取有限项的连加式来逼近一个函数。当总共有N项时,连加式被叫做N阶泰勒展开(Nth-order Taylor approximation)。假设现在存在函数f(x)f(x)f(x),则有:
- 泰勒级数(无限项):
f(x)=∑n=0∞f(n)(a)n!(x−a)nf(x) = \sum_{n=0}^{\infty}\frac{f^{(n)}(a)}{n!}(x-a)^nf(x)=n=0∑∞n!f(n)(a)(x−a)n
其中(x-a)是非常小的任意实数/复数,n!n!n!是n的阶乘,f(n)(a)f^{(n)}(a)f(n)(a)是函数f(x)f(x)f(x)的n阶导数在a点的取值。当a为0时,泰勒级数也被叫做麦克劳思级数。
- 一阶泰勒展开:
f(x)≈∑n=01f(n)an!(x−a)n≈f(a)+f′(a)1!(x−a)\begin{aligned} f(x) &\approx \sum_{n=0}^{1}\frac{f^{(n)}a}{n!}(x-a)^n \\ &\approx f(a) + \frac{f'(a)}{1!}(x-a) \end{aligned} f(x)≈n=0∑1n!f(n)a(x−a)n≈f(a)+1!f′(a)(x−a)
- 二阶泰勒展开:
f(x)≈∑n=02f(n)an!(x−a)n≈f(a)+f′(a)1!(x−a)+f′′(a)2!(x−a)2\begin{aligned} f(x) &\approx \sum_{n=0}^{2}\frac{f^{(n)}a}{n!}(x-a)^n \\ &\approx f(a) + \frac{f'(a)}{1!}(x-a) + \frac{f''(a)}{2!}(x-a)^2 \end{aligned} f(x)≈n=0∑2n!f(n)a(x−a)n≈f(a)+1!f′(a)(x−a)+2!f′′(a)(x−a)2
- N阶泰勒展开:
f(x)≈∑n=0Nf(n)an!(x−a)n≈f(a)+f′(a)1!(x−a)+f′′(a)2!(x−a)2+f′′′(a)3!(x−a)3+...\begin{aligned} f(x) &\approx \sum_{n=0}^{N}\frac{f^{(n)}a}{n!}(x-a)^n \\ &\approx f(a) + \frac{f'(a)}{1!}(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \frac{f'''(a)}{3!}(x-a)^3 + ... \end{aligned} f(x)≈n=0∑Nn!f(n)a(x−a)n≈f(a)+1!f′(a)(x−a)+2!f′′(a)(x−a)2+3!f′′′(a)(x−a)3+...
阶数越大,泰勒展开的值越接近f(x)f(x)f(x)的真实值。
我们可以对损失函数进行泰勒展开。对单一样本而言,我们有损失函数l(yi,Ht−1(xi)+ft(xi))l(y_i, H_{t-1}(x_i) + f_t(x_i))l(yi,Ht−1(xi)+ft(xi)),其中yiy_iyi是已知的常数,因此损失函数可以被看做是只有Ht−1(xi)+ft(xi)H_{t-1}(x_i) + f_t(x_i)Ht−1(xi)+ft(xi)一个自变量的函数,从而简写为l(Ht−1(xi)+ft(xi))l(H_{t-1}(x_i) + f_t(x_i))l(Ht−1(xi)+ft(xi))。
根据一阶泰勒展开,已知:
f(x)≈f(a)+f′(a)1!(x−a)≈f(a)+f′(a)(x−a)\begin{aligned} f(x) &\approx f(a) + \frac{f'(a)}{1!}(x-a) \\ &\approx f(a) + f'(a)(x-a) \end{aligned} f(x)≈f(a)+1!f′(a)(x−a)≈f(a)+f′(a)(x−a)
令泰勒展开中的 x = Ht−1(xi)+ft(xi)H_{t-1}(x_i) + f_t(x_i)Ht−1(xi)+ft(xi),令泰勒展开中的a = Ht−1(xi)H_{t-1}(x_i)Ht−1(xi),则损失函数l(Ht−1(xi)+ft(xi))l(H_{t-1}(x_i) + f_t(x_i))l(Ht−1(xi)+ft(xi))可以被表示为:
l(Ht−1(xi)+ft(xi))≈l(Ht−1(xi))+∂l(Ht−1(xi))∂Ht−1(xi)∗ft(xi)\begin{aligned} l(H_{t-1}(x_i) + f_t(x_i) ) &\approx l(H_{t-1}(x_i)) + \frac{\partial{l(H_{t-1}(x_i))}}{\partial{H_{t-1}(x_i)}} * f_t(x_i) \\ \end{aligned} l(Ht−1(xi)+ft(xi))≈l(Ht−1(xi))+∂Ht−1(xi)∂l(Ht−1(xi))∗ft(xi)
不难发现,该式子中Ht−1(xi)H_{t-1}(x_i)Ht−1(xi)是常数,因此第一部分l(yi,Ht−1(xi))l(y_i, H_{t-1}(x_i))l(yi,Ht−1(xi))也是一个常数。同时,第二部分由导数和ftf_tft组成,其中导数就是梯度,可以写作gig_igi,所以式子可以化简为:
l(Ht−1(xi)+ft(xi))≈常数+gift(xi)\begin{aligned} l(H_{t-1}(x_i) + f_t(x_i) ) &\approx 常数 + g_if_t(x_i) \\ \end{aligned} l(Ht−1(xi)+ft(xi))≈常数+gift(xi)
现在,如果要令lll最小,ft(xi)f_t(x_i)ft(xi)应该等于多少呢?回到我们最初的目标,找出令损失函数lll最小的ftf_tft值:
ft=argminf∑i=1Ml(Ht−1(xi)+ft(xi))≈argminf∑i=1M(常数 +gift(xi))\begin{aligned} f_{t} &=\underset{f}{\operatorname{argmin}} \sum_{i=1}^{M} l\left(H_{t-1}\left(x_{i}\right)+f_{t}\left(x_{i}\right)\right) \\ & \approx \underset{f}{\operatorname{argmin}} \sum_{i=1}^{M}\left(\text { 常数 }+g_{i} f_{t}\left(x_{i}\right)\right) \end{aligned} ft=fargmini=1∑Ml(Ht−1(xi)+ft(xi))≈fargmini=1∑M( 常数 +gift(xi))
常数无法被最小化,因此继续化简:
ft≈argminf∑i=1Mgift(xi)≈argminf⟨gtft(x)⟩\begin{aligned} f_{t} & \approx \underset{f}{\operatorname{argmin}} \sum_{i=1}^{M} g_{i} f_{t}\left(x_{i}\right) \\ & \approx \underset{f}{\operatorname{argmin}}\left\langle g_{t} f_{t}(x)\right\rangle \end{aligned} ft≈fargmini=1∑Mgift(xi)≈fargmin⟨gtft(x)⟩
现在,gtg_tgt是包含了所有样本梯度的向量,ft(x)f_t(x)ft(x)是包含了所有样本在ftf_tft上预测值的向量,两个向量对应位置元素相乘后求和,即表示为向量的内积,由尖括号<>表示。现在我们希望求解向量内积的最小值、并找出令向量内积最小的ft(x)f_t(x)ft(x)的取值,那就必须先找出ft(x)f_t(x)ft(x)的方向,再找出ft(x)f_t(x)ft(x)的大小。
[g1f(x1) + g2f(x2) + g3(fx3)...gM(fxM)][g1,g2,g3....gM] - 梯度向量
[f(x1),f(x2),f(x3)....f(xM)] - ft决策树上输出的所有样本的预测值
- 方向
ft(x)f_t(x)ft(x)的方向应该与gtg_tgt完全相反。向量的内积⟨gtft(x)⟩=∣gt∣∣ft(x)∣cos(α)\langle g_t f_t(x) \rangle = |g_t||f_t(x)|cos(\alpha)⟨gtft(x)⟩=∣gt∣∣ft(x)∣cos(α),其中前两项为两个向量的模长,α\alphaα是两个向量的夹角大小。模长默认为整数,因此当且仅当两个向量的方向完全相反,即夹角大小为180度时,cos(α)cos(\alpha)cos(α)的值为-1,才能保证两个向量的内积最小。假设向量 a = [1,2],向量b是与a的方向完全相反的向量。假设a和b等长,那向量b就是[-1,-2]。因此,与gtg_tgt方向完全相反且等长的向量就是−gt-g_t−gt,ft(x)f_t(x)ft(x)的方向也正是−gt-g_t−gt的方向。
- 大小
对于向量a,除了[-1,-2]之外,还存在众多与其呈180度夹角、但大小不一致的向量,比如[-2,-4], [-0.5,-1],每一个都可以与向量a求得内积。并且我们会发现,当方向相反时,向量b中的元素绝对值越大,b的模长就越长,向量a与b的内积就越小。因此不难发现,⟨gtft(x)⟩\langle g_t f_t(x) \rangle⟨gtft(x)⟩是一个理论上可以取到无穷小的值,那我们的ft(x)f_t(x)ft(x)应该取什么大小呢?答案非常出乎意料:任何大小都无所谓。
回到我们的迭代公式:
Ht(x)=Ht−1(x)+ηft(x)H_t(x) = H_{t-1}(x) + \eta f_t(x) Ht(x)=Ht−1(x)+ηft(x)l(Ht−1(xi)+ft(xi))≈常数+gift(xi)l(H_{t-1}(x_i) + f_t(x_i) ) \approx 常数 + g_if_t(x_i) l(Ht−1(xi)+ft(xi))≈常数+gift(xi)
无论ft(x)f_t(x)ft(x)的大小是多少,我们都可以通过步长η\etaη对其进行调整,只要能够影响H(x)H_(x)H(x),我们就可以影响损失迭代过程中的常数的大小。因此在数学上来说,ft(x)f_t(x)ft(x)的大小可以是−gt-g_t−gt的任意倍数,这一点在梯度下降中其实也是一样的。为了方便起见,同时为了与传统梯度下降过程一致,我们通常让ft(x)f_t(x)ft(x)就等于一倍的−gt-g_t−gt,但也有不少论文令ft(x)f_t(x)ft(x)等于其他值的。在GBDT当中:
ft≈argminf⟨gtft(x)⟩=−gt\begin{aligned} f_t &\approx \mathop{argmin}_{f} \langle g_t f_t(x) \rangle\\ &= -g_t \end{aligned} ft≈argminf⟨gtft(x)⟩=−gt
这就是我们让GBDT当中的弱评估器拟合伪残差/负梯度的根本原因。拟合负梯度其实为GBDT带来了非常多的特点——
首先,通过直接拟合负梯度,GBDT避免了从损失函数找“最优”的过程,即避免了上述证明中求解ft=argminf∑i=1Ml(Ht−1(xi)+ft(xi))f_t = \mathop{argmin}_{f} \sum_{i=1}^{M}l(H_{t-1}(x_i) + f_t(x_i))ft=argminf∑i=1Ml(Ht−1(xi)+ft(xi))的过程,从而大大地简化了计算。
其次,通过拟合负梯度,GBDT模拟了梯度下降的过程,由于结合了传统提升法Boosting与梯度下降,因此才被命名为梯度提升法(Gradient Boosting)。这个过程后来被称为函数空间上的梯度下降(Gradient Descent in Function Space),这是视角为Boosting算法的发展奠定了重要的基础。
最后,最重要的一点是,通过让弱评估器拟合负梯度,弱评估器上的结果可以直接影响损失函数、保证损失函数的降低,从而指向Boosting算法的根本目标:降低偏差。这一过程避免了许多在其他算法中需要详细讨论的问题:例如,每个弱评估器的权重ϕ\phiϕ是多少,以及弱评估器的置信度如何。
在AdaBoost算法当中,损失函数是“间接”影响弱评估器的建立,因此有的弱评估器能够降低损失函数,而有的弱评估器不能降低损失函数,因此要在求和之前,需要先求解弱评估器的置信度,然后再给与置信度高的评估器更高的权重,权重ϕ\phiϕ存在的根本意义是为了调节单一弱评估器对H(x)H(x)H(x)的贡献程度。但在GBDT当中,由于所有的弱评估器都是能够降低损失函数的,只不过降低的程度不同,因此就不再需要置信度/贡献度的衡量,因此就不再需要权重ϕ\phiϕ。
如果去翻阅早期梯度提升机器资料,我们会发现梯度提升树最开始是有求解权重的过程的。当拟合完伪残差之后,我们不直接求解令LLL最小的ftf_tft值,而求解令整体LLL最小的权重ϕ\phiϕ:
求解迭代过程中弱评估器ftf_tft所需的权重ϕt\phi_tϕt,具体公式为:
ϕt=argminϕ∑i=1ML(yi,Ht−1(xi)+ϕtft(xi))\phi_t = \mathop{argmin}_{\phi} \sum_{i=1}^M L\left(y_i,H_{t-1}(x_i) + \phi_tf_t(x_i) \right) ϕt=argminϕi=1∑ML(yi,Ht−1(xi)+ϕtft(xi))
与求解H0H_0H0的式子相似,上述式子表示,找出令∑i=1ML(yi,Ht−1(xi)+ϕtft(xi))\sum_{i=1}^M L\left(y_i,H_{t-1}(x_i) + \phi_tf_t(x_i) \right)∑i=1ML(yi,Ht−1(xi)+ϕtft(xi))最小的常数ϕt\phi_tϕt值。同样,由于ϕt\phi_tϕt是针对全部样本计算出来的,因此ftf_tft上所有样本的预测值前的权重都是ϕt\phi_tϕt,并不存在针对于某一样本的权重。接着,再根据求解出的权重ϕt\phi_tϕt迭代模型,具体来说:
Ht(x)=Ht−1(x)+ηϕtft(x)H_t(x) = H_{t-1}(x) + \eta \phi_t f_t(x)Ht(x)=Ht−1(x)+ηϕtft(x)
在此基础上,Friedman甚至还提出了单独针对决策树的权重计算方法。但我们之前推导中讲解过,只要ft(x)f_t(x)ft(x)的方向正确,ft(x)f_t(x)ft(x)具体的取值并没有那么重要,毕竟可以通过学习率η\etaη进行调整。在有η\etaη、同时又不需要衡量弱评估器置信度的情况下,权重ϕ\phiϕ的意义就很小了。因此现在我们在实现梯度提升树时,已经不再使用带权重的版本,但带权重版本的数学过程与不带权重版本是高度类似的。
讲到这里,梯度提升树相关的知识也就讲解完毕了。在课程当中我们专注于GBDT回归的讲解,是因为GBDT分类问题就是在回归问题的流程上令p(x)=σ(H(x))p(x) = \sigma(H(x))p(x)=σ(H(x)),其中σ\sigmaσ依情况而定可能是softmax也可能是sigmoid或其他函数。如果你对GBDT分类感兴趣,可以阅读原理进阶部分提到的4篇论文,里面有大量关于分类问题的讲解。现在,我们已经了解了整个GBDT的数学流程,这部分流程是未来XGBoost、LGBM等算法的基础。如果你对Boosting算法的数学理论有相应的需求,请务必熟读GBDT原理相关的内容。
LESSON 12.8 原理进阶 (1):GBDT数学流程与残差概念辨析相关推荐
- LESSON 11.4 原理进阶:AdaBoost算法流程详解
2 原理进阶:AdaBoost的求解流程 在使用AdaBoost算法时,我们并不需要对AdaBoost的具体求解流程掌握太过于深入.严格来说,只要知道参数的含义,即便我们完全不了解AdaBoost的求 ...
- Lesson 12.5 softmax回归建模实验
Lesson 12.5 softmax回归建模实验 接下来,继续上一节内容,我们进行softmax回归建模实验. 导入相关的包 # 随机模块 import random# 绘图模块 import ma ...
- Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用
Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用 为了方便后续练习的展开,我们尝试自己创建一个数据生成器,用于自主生成一些符合某些条件.具备某些特性的数据集.相比于传统的机器学 ...
- 网络编程原理进阶___TCP/IP(javaee)
点击跳转 本章重点 网络编程原理进阶 应用层 DNS 传输层 UDP TCP面试重点 `TCP`原理 确认应答 超时重传 连接管理(面试重点) 3次握手 4次挥手 滑动窗口 流量控制 拥塞控制 延时应 ...
- 【520大礼包】《Scratch趣味编程进阶——妙趣横生的数学和算法》免费送啦!
快!关注这个公众号,一起涨姿势- 内容简介 本书将Scratch作为一门程序设计语言看待,通过大量数学和算法方面的编程案例,为广大中小学生提供了一本编程进阶的参考教材.本书根据案例类型分为12章,共有 ...
- Lesson 12.4 逻辑回归建模实验
Lesson 12.4 逻辑回归建模实验 接下来进行逻辑回归的建模实验,首先需要导入相关库和自定义的模块. # 随机模块 import random# 绘图模块 import matplotlib ...
- Lesson 12.3 线性回归建模实验
Lesson 12.3 线性回归建模实验 一.深度学习建模流程 数据准备就绪,接下来就是建模实验环节,在实际深度学习建模过程中,无论是手动实现还是调库实现,我们都需要遵循深度学习建模一般流程.在此 ...
- Direct3D 12工作原理概述
Direct3D 12工作原理概述 这只是Direct3d 12的概述.以后的教程将更深入. Pipeline State Objects (PSO)(MSDN Pipeline States) 管道 ...
- AutoSAR系列讲解(实践篇)8.5-C/S原理进阶
AutoSAR系列讲解(实践篇)8.5-C/S原理进阶 C/S原理进阶 一.同步调用 二.异步调用 1.带时限(Timeout) 2.循环等待(Polling) 3.触发(Trigger) C/S原理 ...
最新文章
- Python 标准库之 shutil
- PXE全自动安装操作系统--centos7.3学习笔记
- arm服务器获取文件路径中文,ssh 访问远程服务器文件路径
- 自定义ViewGroup(1)
- 开源软件和自由软件_自由和开源软件的经济学
- [转]【Linux】一幅图秒懂LoadAverage(负载)
- Hello工作室制作《无人深空》更新档
- 最简单爬虫rvest_告别复制粘贴
- 制作ext4 img的两种方式
- 文本比较/文本对比在线工具
- html 怎么转换,html怎么转换成word?
- 卡塔编程_量子卡塔教您如何在Q#中进行量子编程
- 解决you-get下载视频速度慢和下载MP4文件问题
- 计算机中的网络怎么共享的打印机驱动,如何共享打印机,如何设置打印机共享打印机共享设置图解-中关村在线...
- 如何用搜狗拼音输入法输入希腊字母
- [HTTPD] Linux(Apache)Httpd服务器安装,启动及httpd.conf配置详解
- java为什么匿名内部类的参数引用需要添加final?
- Eclipse配置黑色酷炫主题
- mysql数据库(mariadb)
- 全志A64 lichee目录编译
热门文章
- catia打开后拖动工具栏有残影_Photoshop工具和工具栏概述
- 计算机设计大赛海洋世界,全国大学生海洋文化设计大赛第二届获奖作品(三)...
- Oracle存储过程以及游标
- opencv 标记有数字的区域
- python 提取字符串中的数字
- app h5 上传按钮多选_稿定小课堂之教你如何制作H5
- 基于MATLAB的面向对象编程(5)——对象的保存(save)和载入(load)
- mac安装opencv
- Linux疑难杂症解决方案100篇(二十)-万字长文带你读懂正则表达式(建议收藏)
- 机器学习从入门到精通系列之BP神经网络理论知识详解