1. 程式人生 > >機器學習爬大樹之(GBDT原理)--迴歸篇

機器學習爬大樹之(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分類問題,加油!