机器学习爬大树之(GBDT原理)--回归篇

             集成学习(ensemble learning)想必应该是最为火爆的机器学习算法了,它通过构建并结合多个学习器来完成学习任务;类似于我们长说的“采百家之长”,目前的集成学习方法大致可分为两大类:

              (1)个体学习器间存在强依赖关系,必须串行生成的序列化方法(Adaboost,GBDT);

              (2)个体学习器间不存在强依赖关系,可同时生成的并行化方法(Bagging,随机深林(Random Forest))。

  由于我想尽快学习XGboost,与lightgbm,所有先写下GBDT,但学习是自己的事,以后定将其他的补上,立个Flag!!!

            GBDT(Gradient Boosting Decision Tree)是学习XGBoost、LightGBM的基础,由于这部门内容较多,故将分为三篇来写,分为回归篇、二分类篇、多分类篇。本篇主要讲GBDT回归的原理,并举例实现其过程。

            GBDT是提升树优化算法,故其基学习器也是决策树,但决策树很多 (如ID3、C4.5、CART等),到底用哪一种树呢?在GBDT中我们采用CART作为其基学习器。CART在上篇文章已经很详细地讲到,简单的说,当用于分类任务时,CART采用基尼指数作为划分准则;当用于回归任务时,CART采用平方误差最小准则。

            GBDT的关键之处在于其利用损失函数的负梯度在当前模型的值作为提升树算法中的残差的近似值来来拟合一个回归树,因为负梯度是一个连续值,所以无论是GBDT用于回归还是分类,其基学习器都采用回归树。

           有了基学习器,提升树模型可以表示为决策树的加法模型:

                 \large f(x)=\sum _{m=1}^MT(x;\theta _m)

   其中,\large T(x;\theta _m)表示决策树; \large \theta _m为决策树的参数;\large M为树的个数。

 GB的算法流程总结如下:

 算法第三步(第一步后面讲)

        这一步\large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{m-1}(x)}}就是用负梯度在当前模型\large \boldsymbol{F_{m-1}(x)}的值来近似的表示残差值;可以理解为我们的每一颗回归树就是拟合这个残差值\large \boldsymbol{\widetilde{y_i}}:

      若我们选取平方损失函数(quadratic loss function)为:

          \large \boldsymbol{L(y_i,F(x_i))=\frac{1}{2}\ast (y_i-F(x_i))^2}

          上式对\large \boldsymbol{F(x_i)}求偏导得其负梯度:

          \large \boldsymbol{-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]=(y_i-F(x_i))}

          将当前的模型带入\large \boldsymbol{F(x_i)=F_{m-1}(x_i)},则有:

         \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{m-1}(x)}=(y_i-F_{m-1}(x_i))};

       从上式我们可以看出来,若选取的损失函数为平方损失函数,则我们拟合的残差为真实的。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    若我们选取绝对损失函数(absolute loss function):

        \large \boldsymbol{L(y_i,F(x_i))=\left |(y_i-F(x_i)) \right |}

        上式对\large \boldsymbol{F(x_i)}求偏导得其负梯度,将当前的模型带入\large \boldsymbol{F(x_i)=F_{m-1}(x_i)},则有:

        \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{m-1}(x)}=sign(y_i-F_{m-1}(x_i))}

        其中\large \boldsymbol{sign}是符号函数。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   若我们选取对数损失函数(logarithmic loss function):

         \large \boldsymbol{L(y_i,F(x_i))=y_i\ast log(h_{m}(x_i))+(1-y_i)\ast log(1-h_{m}(x_i)) }   ;

         其中\large \boldsymbol{h_m(x_i)=\frac{1}{1+e^{(-F_m(x_i))}}};

        上式对\large \boldsymbol{F(x_i)}求偏导得其负梯度,将当前的模型带入\large \boldsymbol{F(x_i)=F_{m-1}(x_i)},则有:

      \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{m-1}(x)}=y_i-\frac{1}{1+e^{(-F_{m-1}(x_i))}}}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 若我们选取Huber损失函数: 

      \large \boldsymbol{L(y_i,F_m(x_i))=\left\{\begin{matrix} \frac{1}{2}(y_i-F_m(x_i))^2 ,&\left | y_i-F_m(x_i) \right |\leq \delta \\ \delta (\left |y_i-F_m(x_i) \right |-\delta /2),& \left | y_i-F_m(x_i) \right |> \delta \end{matrix}\right.}

     则有:

        \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{m-1}(x)}=\left\{\begin{matrix} y_i-F_{m-1}(x_i), &\left | yi-F_{m-1}(x_i) \right |\leq \delta \\ \delta \cdot sign(y_i-F_{m-1}(x_i)),& \left | yi-F_{m-1}(x_i) \right |> \delta \end{matrix}\right.}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

算法第四步:

       \large \boldsymbol{\partial _m}其实就是第m个基学习器(CART回归树),采用启发式的方法,根据平方误差最小化准则找到最优划分点,构建一个最优回归树 ,当前回归树能最好的拟合当前的残差(使残差最小) 。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

算法第五步:

   在friedman论文中提到\large \boldsymbol{\rho_m}的计算是一个线性搜索(Line search)的过程 ,通俗的讲\large \boldsymbol{\rho _m}就是我们以前接触的学习率,而在 GBDT中的学习率是使得总损失的误差在当前模型下最小而学习来的,在每一轮 \large \boldsymbol{\rho _m}都不同,可以防止过拟合。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

算法第一步:

    \large \boldsymbol{F_0(x)}初始化不是零,与Adaboost的初始化不同(Adaboost中\large \boldsymbol{F_0(x)}=0),这是因为我们在生成第\large \boldsymbol{m=1}的基学习器的时候是需要将\large \boldsymbol{F_{m-1}(x)}带入负梯度公式生成残差,所以\large \boldsymbol{F_0(x)}的初始值不为0,对于不同的损失函数,其初始化的值也不尽相同,现总结如下:

  

损失函数 初始化

平方损失函数:

\large \boldsymbol{\bar{y}}
对数损失函数: \large \boldsymbol{log\frac{\bar{y}}{1-\bar{y}}}
绝对损失函数 \large \boldsymbol{median\left \{ y_i \right \}_{1}^{N}}
Huber损失函数 \large \boldsymbol{median\left \{ y_i \right \}_{1}^{N}}

  以一个例子来求下各个损失函数的初始化:

   

\large x_i 1 2 3 4 5 6 7 8 9 10
\large y_i 4.50 4.75 4.91 5.34 5.80 7.05 7.90 8.23 8.70 9.00

初始化为:

损失函数 初始化

平方损失函数:

\large \boldsymbol{\bar{y}}=6.618
绝对损失函数 \large \boldsymbol{median\left \{ y_i \right \}_{1}^{N}}=6.425
Huber损失函数 \large \boldsymbol{median\left \{ y_i \right \}_{1}^{N}}=6.425

对数损失函数用于分类的初始化为:

编号 1 2 3 4 5 6
x 0.5 0.4 0.1 0.6 0.3 0.2
y 0 0 1 0 1 0
对数损失函数: \large \boldsymbol{log\frac{\bar{y}}{1-\bar{y}}=log(\frac{1}{2})}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GBDT原理细节:

               上面是GB的总流程,若我们将基学习器选为CART回归树,就是GBDT了,现在我们看下如何使用GBDT建立一个回归树的流程,我们选择平方损失函数为例,给出GBDT的算法流程如下:

第一步:

      第一步就是上面讲的初始化的过程,由于我们是选取的平方损失函数,所以初始值为:

          \large \boldsymbol{F_0(x)=\bar{y}}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第二步:

   用负梯度在当前模型的值来近似残差,由于我们选取的是平方损失函数,所以这里的残差就是真实值,但对于其他的损失函数,由于求残差的真实值比较困难,所以用负梯度近似代替。          

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第三步:

  通过平方误差最小准则,采用启发式的思想,将训练集\large \boldsymbol{\left \{ \widetilde{y_i},x_i \right \}_{1}^{N}}划分为互不相交的各个叶子结点区域\large \boldsymbol{\left \{ R_{1m},R_{2m},...,R_{Jm} \right \}}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第四步:

 通过上一步,我们得到了叶子结点的区域,那么对于每个叶子结点的输出值到底是多少呢?其实叶子结点的取值跟我们选取的损失函数有很大的关系,例如:

    (1)选取平方损失函数时:

             \large \boldsymbol{\gamma_{jm}=ave_{x_i\in R_{jm}}\widetilde{y_i}}

           其中\large \boldsymbol{\widetilde{y_i}}为负梯度值(残差)。

   

    (2)选取绝对损失函数时:

            \large \boldsymbol{\gamma_{jm}=median_{x_i\in R_{jm}}\left \{ y_i-F_{m-1}(x_i) \right \}}

           其中\large \boldsymbol{\widetilde{y_i}}为负梯度值(残差)。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第五步:

 这一步就是拟合基学习器的过程,将训练好的当前学习器加到前面的加法模型(强学习器)中,这里依旧会有学习率,在下面的例子中我们会看到。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GBDT实例讲解:

           下面我们通过一个实例来一步步时间GBDT回归树的生成,现初始条件假设如下:

     (1)损失函数选取:平方损失函数;

     (2)树的深度为1(会讲一个深度大于等于2的情况);

     (3)平方损失最小化准则选取最佳划分点;

     (4)树的棵树\large \boldsymbol{M=2};

     (5)学习率\large \boldsymbol{{\color{Red} \eta =2}};

\large x_i 1 2 3 4 5 6 7 8 9 10
\large y_i 5.56 5.70 5.91 6.40 6.80 7.05 8.90 8.70 9.00 9.05

    第一步:初始化

          我们选取的是平方损失函数\large \large \boldsymbol{L(y,F(x))};

          所以初始化为:

                \large \boldsymbol{F_0(x)=\bar{y}}=7.307

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第一颗树的建立\large \boldsymbol{M=1}

  第二步:负梯度拟合残差

           \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{0}(x)}=(y_i-F_{0}(x_i))=(y_i-7.307)}

           将\large \boldsymbol{y_i}带入上式,得下表:

\large x_i 1 2 3 4 5 6 7 8 9 10
\large \boldsymbol{\widetilde{y_i}} -1.747 -1.607 -1.397 -0.907 -0.507 -0.257 1.593 1.393 1.693 1.743

      因为我们选取的的平方损失函数,所以上面的\large \boldsymbol{\widetilde{y_i}}是残差的真实值,若选取其他的损失函数,那么\large \boldsymbol{\widetilde{y_i}}就是残差的近似值。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 第三、四步:找到最佳的划分点,划分区域,并输出叶子结点的值

          这个步骤与前面的文章中CART划分是一样的,采用启发式的思想,逐一选取各个划分点,再从中选取使平方损失函数最小的划分点即可:

          以划分点\large \boldsymbol{s=1.5}为例,将样本集分为:

         \large \boldsymbol{R_{11}=\left \{ 1 \right \}},          \large \boldsymbol{R_{12}=\left \{ 2,3,4,5,6,7,8,9,10 \right \}};

         由公式\large \boldsymbol{\gamma_{jm}=ave_{x_i\in R_{jm}}\widetilde{y_i}}得:

            \large \boldsymbol{\gamma_{11}=-1.747},           \large \boldsymbol{\gamma_{21}=0.194}   

         平方误差最小化公式为:

         \large \boldsymbol{m(s)=\min_{s}\left [ \min_{\gamma_{11}}\sum _{x_i\in R_{11}}Loss(\widetilde{y_i},\gamma_{11}) + \min_{\gamma_{21}}\sum _{x_i\in R_{21}}Loss(\widetilde{y_i},\gamma_{21})\right ]}    

         将\large \boldsymbol{\widetilde{y_i}}\large \boldsymbol{\gamma_{11}=-1.747}\large \boldsymbol{\gamma_{21}=0.194},带入上面的公式,得:

         \large \boldsymbol{m(s=1.5)}=15.72

         其他的划分点求最小平方误差的方法与上相似,如果还是不明白请参考我前一章关于CART的文章,仔细看看就不难理解了,现给出所有划分点的最小平方误差,见下表:

\large \boldsymbol{s} 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5
\large \boldsymbol{m(s)} 15.72 12.08 8.37 5.78 3.91 1.93 8.00

11.76

15.74

        从上表中可以看出,当\large \boldsymbol{s=6.5}时,平方误差\large \boldsymbol{m(s)}最小,因此划分两个叶子结点区域:

         \large \boldsymbol{R_{11}=\left \{ 1,2,3,4,5,6 \right \}}              \large \boldsymbol{R_{21}=\left \{7,8,9,10 \right \}}

       因为我们初始化的深度为1,所以划分到这就直接输出叶子结点的值了:

       \large \boldsymbol{\gamma_{11}=-1.07}                \large \boldsymbol{\gamma_{21}=1.605}

       若我们的初始化的深度为2(大于2的情况类似),这时\large \boldsymbol{R_{11},R_{12}}就不是叶子结点,而是内部结点,此时的深度为1,所以使用上面类似的步骤,对\large \boldsymbol{R_{11},R_{12}}进一步的划分,如下图:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   第五步:拟合第一颗树  

       此时第一个树已经建立,更新\large \boldsymbol{F_1(x_i)}的值为:

       \large \boldsymbol{F_1(x_i)=F_0(x_i)+{\color{Red} \eta }*\sum_{m=1}^{2}\sum _{j=1}^{1}\gamma _{j1}*I(x_i\epsilon R_{jm}) }

                       \large \boldsymbol{=7.307+{\color{Red} 0.1}*\sum _{j=1}^{1}\gamma _{j1}*I(x_i\epsilon R_{j1}) }

    其中\large \eta是学习率,可以仔细的想想,如果我们直接加上叶子结点的输出值,很容易导致过拟合,所以加上学习率,使其跳出过拟合。例如当取\large \boldsymbol{x_1}是,我们计算它的输出值:

      \large \boldsymbol{F_1(x_1)=F_0(x_1)+{\color{Red} \eta }*\sum_{m=1}^2\sum _{j=1}^{1}\gamma _{j1}*I(x_1\epsilon R_{j1}) }

                      \large \boldsymbol{=7.307+{\color{Red} 0.1}*(-1.07) =7.2}

   至此,第一颗树已经拟合完毕,下一步我们用当前模型\large \boldsymbol{F_1(x_1)=7.2}来拟合第二颗树。        

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第二颗树的建立:

   第一步:更新\large \boldsymbol{F_1(x_1)}的值

     \large \boldsymbol{M=2}

    \large \boldsymbol{F_1(x_1)=7.2}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   第二步:负梯度拟合残差

       \large \boldsymbol{\widetilde{y_i}=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \right ]_{F(x)=F_{1}(x)}=(y_i-F_{1}(x_i))=(y_i-7.2)} 

       将\large \boldsymbol{y_i}带入上式,得下表:

\large x_i 1 2 3 4 5 6 7 8 9 10
\large \boldsymbol{\widetilde{y_i}} -1.64 -1.5 -1.29 -0.8 -0.4 -0.15 1.7 1.5 1.8 1.85

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 第三、四步:找到最佳的划分点,划分区域,并输出叶子结点的值

      方法与第一颗树的步骤一样,所以直接给出各个划分点的平方误差表:   

\large \boldsymbol{s} 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5
\large \boldsymbol{m(s)} 15.72 12.08 8.37 5.78 3.91 1.93 8.00

11.76

15.74

      

     从上表中可以看出,当\large \boldsymbol{s=6.5}时,平方误差\large \boldsymbol{m(s)}最小,因此划分两个叶子结点区域:

         \large \boldsymbol{R_{12}=\left \{ 1,2,3,4,5,6 \right \}}              \large \boldsymbol{R_{22}=\left \{7,8,9,10 \right \}}

     所以划分到这就直接输出叶子结点的值了:

       \large \boldsymbol{\gamma_{12}=-1.07}                \large \boldsymbol{\gamma_{22}=1.605}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    

第五步:拟合第二颗树  

       此时第二颗树已经建立,更新\large \boldsymbol{F_2(x_i)}的值为:

       \large \boldsymbol{F_2(x_i)=F_0(x_i)+{\color{Red} \eta }*\sum _{j=1}^{2}\gamma _{j1}*I(x_i\epsilon R_{j1}) }

                       \large \boldsymbol{=7.307+{\color{Red} 0.1}*\sum _{j=1}^{2}\gamma _{j1}*I(x_i\epsilon R_{j1}) }

       同理,若我们想计算\large \boldsymbol{x_1}的输出值:

     

     \large \boldsymbol{F_2(x_1)=F_0(x_1)+{\color{Red} \eta }*\sum _{j=2}^{1}\gamma _{j1}*I(x_1\epsilon R_{j1}) }

                      \large \boldsymbol{=7.307+{\color{Red} 0.1}*(-1.07-1.07)=7.083}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

至此GBDT回归树生成完了,我们总结一下GBDT的思路,首先初始化,然后用负梯度在当前模型的值来近似残差,接着采用CART回归树中启发式的思想,采用平方误差最小化原则找到最小划分点,生成回归树,然后用加法模型建立GBDT回归树!

下一篇为GBDT分类问题,加油!

猜你喜欢

转载自blog.csdn.net/weixin_41580067/article/details/85008527
今日推荐