很久以前写的Xgboost有一些没写好,现在填坑_part1【xgboost是gbdt升级版】

拟合是外在,优化是核心

GBDT也好,XGBOOST也好,目标就是寻找多棵树的预测结果,合起来比如简单求和、加权求和,与实际值尽量接近(损失函数最小)。

本质工作就是最小化损失函数,使得预测值与实际值尽量接近

1.以GBDT来看树的生成

拿起笔,拿一张纸,边写边画,门槛不高,易懂,还是会损失一些严谨性。

既然目标是找到多棵树(树是二叉树,多叉树可等价为一个多层的二叉树),合起来(比如求和)后,样本的预测值与实际值尽量接近,那么我们首先来解决一个问题:

1.1 叶子节点值如何确定:损失函数求最优

假设已经存在了 t − 1 t-1 t1棵树,如何设计第 t t t棵树,使得经过第 t t t棵树后,整体样本的预测值与实际值尽量接近?

  1. 假设已经存在了 t − 1 t-1 t1棵树( t = 1 t=1 t=1时,就是GBDT/XgBoost的初始状态), m m m个样本,每个样本的实际值也就是label为 y i r y^r_i yir,其中 i = 1 , 2 , 3... m i=1,2,3...m i=1,2,3...m
  2. 每个样本第 k k k棵树的预测值(叶子节点值)为 w i k w^k_i wik,其中 k = 1 , 2... t − 1 k=1,2...t-1 k=1,2...t1 i = 1 , 2 , 3... m i=1,2,3...m i=1,2,3...m
  3. 每个样本前面 t − 1 t-1 t1棵树的预测值之和 y i t − 1 = ∑ k = 1 t − 1 w i k y^{t-1}_i = \sum_{k=1}^{t-1}w_i^k yit1=k=1t1wik i = 1 , 2 , 3... m i=1,2,3...m i=1,2,3...m
  4. 对于第 t t t棵树,先假设这棵树不分裂,只有一个根节点、也是叶子节点,那么这m个样本都分配到这个节点,那么m个样本在这颗树的预测值 w i t w^t_i wit是相等的,即 w 1 t = w 2 t = . . . = w m t {w^t_1}={w^t_2}=...={w^t_m} w1t=w2t=...=wmt,那么,请问 w i t w^t_i wit取值多少时能使得m个样本的 y i t y^{t}_i yit与label值 y i r y^r_i yir整体最接近?
  5. 首先,如何衡量m个样本的 y i t y^{t}_i yit与label值 y i r y^r_i yir的整体接近程度呢,构建一个损失函数 L = 1 / m ∗ ∑ i = 1 m l ( y i t , y i r ) L=1/m*\sum_{i=1}^ml(y^{t}_i,y^r_i) L=1/mi=1ml(yit,yir),当 L L L越小时,m个样本的 y i t y^{t}_i yit与label值 y i r y^r_i yir的整体越接近;
  6. 先做一个简单的,假设使用平方损失函数也就是 L = 1 / m ∗ ∑ i = 1 m ( y i t − y i r ) 2 L=1/m*\sum_{i=1}^m(y^{t}_i-y^r_i)^2 L=1/mi=1m(yityir)2,代入3的公式得到 L = 1 / m ∗ ∑ i = 1 m ( y i t − 1 + w i t − y i r ) 2 L=1/m*\sum_{i=1}^m(y^{t-1}_i+w^t_i-y^r_i)^2 L=1/mi=1m(yit1+wityir)2,对于构建 t t t棵树的时候,前面 t − 1 t-1 t1棵树已经生成,所以 y i t − 1 y^{t-1}_i yit1可以看做常数, y i r y^r_i yir本来也是固定的,所以可以假设这么一个常数 c i t − 1 = y i r − y i t − 1 c^{t-1}_i=y^r_i-y^{t-1}_i cit1=yiryit1 L L L可以变为 L = 1 / m ∗ ∑ i = 1 m ( y i t − 1 + w i t − y i r ) 2 = 1 / m ∗ ∑ i = 1 m ( w i t − c i t − 1 ) 2 L=1/m*\sum_{i=1}^m(y^{t-1}_i+w^t_i-y^r_i)^2=1/m*\sum_{i=1}^m(w^t_i-c^{t-1}_i)^2 L=1/mi=1m(yit1+wityir)2=1/mi=1m(witcit1)2
  7. 进一步,利用4中 w i t w^t_i wit都相等,设为 x x x,对于 L L L换个高中就熟悉的形式 L = 1 / m ∗ ∑ i = 1 m ( x − c i t − 1 ) 2 L=1/m*\sum_{i=1}^m(x-c^{t-1}_i)^2 L=1/mi=1m(xcit1)2是不是很熟悉了, L L L是关于 x x x的二次函数,二次函数求最值,很简单吧
  8. 恩,二次函数求极值会发现 x = 1 / m ∗ ∑ i = 1 m c i t − 1 x=1/m*\sum_{i=1}^mc^{t-1}_i x=1/mi=1mcit1,是不是就是 m m m个样本在 t − 1 t-1 t1树后残差 y i r − y i t − 1 y^r_i-y^{t-1}_i yiryit1的平均值
  9. 所以,在损失函数为平方损失的时候,会发现第 t t t棵树学习的恰好是前 t − 1 t-1 t1棵树的残差,这是损失函数最小化时的表象

1.2 一次分裂的分裂点选择:枚举选最优

前面考虑的是第 t t t棵树不分裂,只有一个根节点,现在要求第 t t t棵树分裂1次,使得经过第 t t t棵树后,整体样本的预测值与实际值尽量接近?

  1. 继续画一画, m m m个样本有 j j j个特征,每个特征分裂点个数为 a j a_j aj,那么枚举的话,可以生成 ∑ i = 1 j a i \sum_{i=1}^ja_i i=1jai种二叉树;从中,随便拿一个二叉树 T r e e s Tree_s Trees
  2. 按照该树选择的特征和分裂点,一部分样本分配到左节点 N l e f t {N}_{left} Nleft,叶子节点取值为 w s , l e f t w_{s,left} ws,left,另一部分样本分配到右节点 N r i g h t {N}_{right} Nright,叶子节点取值为 w s , r i g h t w_{s,right} ws,right,这个时候 w s , l e f t w_{s,left} ws,left w s , r i g h t w_{s,right} ws,right的取值不用再说了吧,为使得损失函数 L s L_s Ls最小,继续上面的最优化求解,结果为这个叶子节点下样本残差的均值,此时的 L s L_s Ls也是 T r e e s Tree_s Trees对应的最优值;
  3. ∑ i = 1 j a i \sum_{i=1}^ja_i i=1jai种二叉树中,哪一棵树的 L s L_s Ls最小,就是这一轮分裂枚举的最优二叉树

1.3 多次分裂的分裂点选择:复杂度计算+贪婪策略

进一步,前面考虑的是要求第 t t t棵树只分裂1次,使得经过第 t t t棵树后,整体样本的预测值与实际值尽量接近,那么现在要求分裂2次、3次、 h h h次、任意次呢,怎么做

答案:大家都知道,用的贪婪策略,也就是先第一层遍历特征和分裂点,寻找最优的分裂点和叶子节点值;然后下一层也如此,一层一层下去。

现在我们来想想为什么选择这个策略:

  1. 先看看决策树生成的复杂度,第一层根节点最优分裂,对于 m m m个样本,有 j j j维特征,每个特征可分裂点数为 a j a_j aj,必然存在 a j ≤ m a_j\leq m ajm,那么第一层枚举特征、分裂点的种类数为 s 1 = ( ∑ i = 1 j a i ) ≤ j ∗ m s_1=(\sum_{i=1}^ja_i)\leq j*m s1=(i=1jai)jm,也就是说,枚举特征、特征分割点,需要遍历 s 1 s_1 s1次,取 L s L_s Ls最小的作为这一轮分裂选择;如果计算一次 L s L_s Ls的时间成本为 T c o n s T_{cons} Tcons,那么这一层枚举寻优时间消耗为 s 1 ∗ T c o n s ≤ j ∗ m ∗ T c o n s s_1*T_{cons}\leq j*m*T_{cons} s1TconsjmTcons
  2. 第1层根节点分裂后第2层左节点样本数 m 2 , l m_{2,l} m2,l,右节点样本数为 m 2 , r m_{2,r} m2,r,满足 m 2 , l + m 2 , r = m m_{2,l}+m_{2,r}=m m2,l+m2,r=m,第2层左节点寻找最优分裂,枚举次数为 s 2 , l ≤ j ∗ m 2 , l s_{2,l}\leq j*m_{2,l} s2,ljm2,l,同样,右侧节点寻找最有分裂,枚举次数为 s 2 , r ≤ j ∗ m 2 , r s_{2,r}\leq j*m_{2,r} s2,rjm2,r,整体的枚举次数 s 2 = s 2 , l + s 2 , r ≤ j ∗ m 2 , l + j ∗ m 2 , r = j ∗ m s_2=s_{2,l}+s_{2,r}\leq j*m_{2,l}+j*m_{2,r}=j*m s2=s2,l+s2,rjm2,l+jm2,r=jm;这一层枚举寻优时间消耗为 s 2 ∗ T c o n s ≤ j ∗ m ∗ T c o n s s_2*T_{cons}\leq j*m*T_{cons} s2TconsjmTcons
  3. 你会发现,每一次层枚举次数的上边界值为 j ∗ m j*m jm,当然这只是边界值,实际的情况应该是 j ∗ 10 j*10 j10或者 j ∗ 100 j*100 j100这种,就是把特征按照分位点或者什么规则分成10个区间、100个区间等,就不细究了。这里重点就是,每一层的枚举花费时间都是一个级别,都是 j ∗ m ∗ T c o n s j*m*T_{cons} jmTcons这个级别
  4. 关键点来了:对于深度为D层的树,你要找到数的最优结构,枚举次数是 ( j ∗ m ) D (j*m)^D (jm)D,到这里,你发现了,枚举最优树结构的复杂度是指数级别,因此选择贪婪策略是妥协选择。
  5. 贪婪做法:先遍历第1层选最优,再到第2层选最优…然后到D层,复杂度变为 ( j ∗ m ) ∗ D (j*m)*D (jm)D,哦豁,相对来说是线性级别。当然,贪婪的结果就是得到的结果是局部最优,不一定是全局最优。
  6. 这就是实际情况,并不一定需要全局最优,局部最优也够解决问题了

2.再看Xgboost损失函数

2.1 损失函数一般化,后面寻优策略本质未变

损失函数一般化,二阶近似,加上考虑模型复杂度的正则项

一步步来,我们先搬出来上面的旧损失函数:

L = ∑ i = 1 m l ( y i t , y i r ) L=\sum_{i=1}^ml(y^{t}_i,y^r_i) L=i=1ml(yit,yir)

当时 l ( y i t , y i r ) l(y^{t}_i,y^r_i) l(yit,yir)假设为平方损失,后面就是一个一般的函数。

同样,与咱们上面的「1.1 叶子节点值如何确定」一样,仍然先考虑第 t t t棵树不分裂节点,样本都在这个节点下,预测值 w i t w_i^t wit都相等,原来的损失函数改一下到xgboost论文里的函数:

L = ∑ i = 1 m l ( y i t , y i r ) + γ ∗ T + 1 2 ∗ ( w i t ) 2 L=\sum_{i=1}^ml(y^{t}_i,y^r_i)+\gamma *T +\frac{1}{2}* (w_i^t)^2 L=i=1ml(yit,yir)+γT+21(wit)2

后面的2项我在以前的博客说过啦:
在这里插入图片描述
我们重点来聊聊 l ( y i t , y i r ) l(y^{t}_i,y^r_i) l(yit,yir),按照上文可以写成:

l ( y i t , y i r ) = l ( y i t − 1 + w i t , y i r ) l(y^{t}_i,y^r_i)=l(y^{t-1}_i+w^t_i,y^r_i) l(yit,yir)=l(yit1+wit,yir)

我先假设一下,大家的数学水平在多年社会毒打后,停留在高中、大一这个层次,印象中留下的只有导数这么点感觉,我们把上面的形式换一个熟悉一点的情况

l ( y i t , y i r ) = l ( y i t − 1 + w i t , y i r ) → l ( x 0 + Δ x , c ) l(y^{t}_i,y^r_i)=l(y^{t-1}_i+w^t_i,y^r_i)\rightarrow l(x_0+\Delta x,c) l(yit,yir)=l(yit1+wit,yir)l(x0+Δx,c)

然后,设计到泰勒展开式,这个呢,你可以百度一下,意思就是在 x = x 0 x=x_0 x=x0处用一个多项式 f m u l t i ( x 0 ) f_{multi}(x_0) fmulti(x0)来近似表示原函数,要求这个新的多项式函数在 x = x 0 x=x_0 x=x0处的函数值、1阶导、各级导数都与原函数相等:

l ( x 0 + Δ x , c ) ≈ l ( x 0 , c ) + ∂ l ( x , c ) ∂ x x = x 0 ∗ Δ x + 1 2 ∗ ∂ l 2 ( x , c ) ∂ x 2 x = x 0 ∗ Δ x 2 l(x_0+\Delta x,c) \approx l(x_0,c)+\frac{\partial l(x,c)}{\partial x}_{x=x_0}*\Delta x+\frac{1}{2}*\frac{\partial l^2(x,c)}{\partial x^2}_{x=x_0}*\Delta x^2 l(x0+Δx,c)l(x0,c)+xl(x,c)x=x0Δx+21x2l2(x,c)x=x0Δx2

写到这里,把 x 0 x_0 x0换回去 y i t − 1 y^{t-1}_i yit1 Δ x \Delta x Δx换回去 w i t w^t_i wit,然后细品一下,细细品:

l ( y i t − 1 + w i t , y i r ) ≈ 1 2 a i ∗ ( w i t ) 2 + b i ∗ ( w i t ) + c i l(y^{t-1}_i+w^t_i,y^r_i) \approx \frac{1}{2}a_i*(w^t_i)^2+b_i*(w^t_i)+c_i l(yit1+wit,yir)21ai(wit)2+bi(wit)+ci

其中 a i = ∂ l 2 ( x , c ) ∂ x 2 x = x 0 a_i=\frac{\partial l^2(x,c)}{\partial x^2}_{x=x_0} ai=x2l2(x,c)x=x0 b i = ∂ l ( x , c ) ∂ x x = x 0 b_i=\frac{\partial l(x,c)}{\partial x}_{x=x_0} bi=xl(x,c)x=x0 c i = l ( x 0 , c ) c_i=l(x_0,c) ci=l(x0,c)

(这里采用的符号、变量名很业余,很不严谨,只是方便回忆起高中数学、大学数学的感觉,好理解,理解是目的,形式咱先忍一忍…)

到这里,是不是发现损失函数也是一个二次函数,继续重新走上面的路「1.以GBDT来看树的生成:1.1叶子节点值如何确定;1.2一次分裂的分裂点选择;1.3 多次分裂的分裂点选择」,是不是又是二次函数求最值、枚举取最优,完事儿?

ps:还记得平方损失时,叶子节点数值 w i t w_i^t wit是节点样本的均值,那么看看上面新的损失函数二次近似以后叶子节点值是多少:

以节点不分离为例,此时 T = 1 T=1 T=1

L = ∑ i = 1 m ( 1 2 a i ∗ ( w i t ) 2 + b i ∗ ( w i t ) + c i ) + γ + 1 2 ∗ ( w i t ) 2 L=\sum_{i=1}^m(\frac{1}{2}a_i*(w^t_i)^2+b_i*(w^t_i)+c_i)+\gamma +\frac{1}{2}* (w_i^t)^2 L=i=1m(21ai(wit)2+bi(wit)+ci)+γ+21(wit)2

二次函数求最值,不多说,还是如此的简单:

w i t ∗ = − ∑ 1 m b i γ + ∑ 1 m a i {w_i^t}^*=-\frac{\sum_1^mb_i}{\gamma+\sum_1^ma_i} wit=γ+1mai1mbi

虽说后面的部分有工程上的细节优化,但是不改贪婪+枚举寻优的本质

2.2 看下正则和二阶近似

1.正则提高泛化能力

实话说,原理上我也没仔细研究过,暂时贴一下人家的回答,我有空回头研究,https://www.zhihu.com/question/20700829:



在这里插入图片描述看见没,人家这叫专业!

2.为啥是二阶近似,而不是一阶,为了快?

这个话题太专业了,看看人家的回答吧。

借用https://www.jiqizhixin.com/articles/2020-02-27-5的说法:

(1)直观感觉上
假设如果我们希望找到 L L L的「谷底」:
采用一阶梯度,也就是坡度的陡和缓来确定步子要迈多大;
而坡度本身也是有变化的,即逐渐变陡或变缓
之前我们可以慢慢多走几步,就能根据坡度的变化直接调整;
如果能用二阶梯度,相当于梯度的梯度,那么也就知道坡度变化的趋势,因此一步就能走的更精准。
在这里插入图片描述
(2) 二阶优化,就是单次计迭代计算量增加了,但是每一步走得更精准,因而迭代步数更少,这是二阶梯度算法 Shampoo 表现在这里插入图片描述
(3) 举一个不恰当,但是很直观的例子,拿二次函数寻最优来看,按一阶优化,要走几步才能到最低点,每一步计算下一阶导数就行;按二阶优化牛顿法,一步到位,但是要计算一阶导数和二阶导数,牛顿法我就不写公式了,看下这里https://blog.csdn.net/Im_Chenxi/article/details/80546742。

在这里插入图片描述

3.接着看Xgboost性能加速(待填坑)

4.看lightGBM性能加速(待填坑)

小结

xgboost果然是加强版的gbdt,工程上的优化先不说,损失函数一般化这不就是明显的个例到一般的升华么

另外,上次我说判断力最重要,后来想想也不对,还是执行力在前面,只敢想不敢做,哪来的经验积累,哪来的样本训练判断力,都是空想了

「小时候自己十分好奇,同样是主角,为什么永远都是太一的亚古兽先进化。直到长大后才明白,都是因为:只有拥有了勇气,才会有友情,爱心,纯真,诚实,知识,光明,最后才会充满希望。」
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值