1. 程式人生 > >機器學習回顧篇(15):整合學習之GDBT

機器學習回顧篇(15):整合學習之GDBT

 

 

 

 

 

1 引言¶

梯度提升樹演算法(Gradient Boosting Decision Tree,GBDT)是一個非常經典的機器學習演算法,和我們前面介紹過的Adaboost演算法一樣,都是提升學習系列演算法中的一員。從“梯度提升樹”這個演算法名稱中我們也可以看出,這又是一個決策樹的整合演算法,更進一步地說,這個演算法是以CART決策樹演算法作為基學習演算法的一種整合演算法。對於CART決策樹演算法,在之前的部落格中已經有詳細的介紹,在閱讀本文之前請務必先理解CART決策樹演算法。接下來,本文將會從提升樹開始,逐漸深入的介紹GBDT演算法。

 

2 提升樹¶

關於提升樹,我們可以從字面上進行理解,可以認為提升樹就是一種以決策樹作為基學習演算法的一種提升學習演算法,可以用來解決分類問題,也可以用於解決迴歸問題。當用於分類問題時,提升樹演算法只需將AdaBoost演算法中的基本學習器限制為二類分類樹即可,可以說這時的提升樹演算法是AdaBoost演算法的特殊情況,本文不再細述,且本文主要介紹的GBDT演算法無論是在分類問題中還是迴歸問題彙總,都是從迴歸提升樹的優化而來,所以下面敘述內容主要以迴歸提升樹為主。
提升樹模型可以看做是使用加法模型對決策樹的線性組合: $${f_M}(x) = \sum\limits_{m = 1}^M {T(x;{\Theta _m})} \tag {1}$$ 式中,${f_M}(x)$是提升樹的數學模型,$M$表示決策樹的數量,${T(x;{\Theta _m})}$表示第$m$棵決策樹,${{\Theta _m}}$表示決策樹的引數。對於引數${{\Theta _m}}$的集合$\Theta = \{ {\Theta _1},{\Theta _2}, \cdots ,{\Theta _M}\} $,我們選取的準則是對於集合$D = \{ ({x_1},{y_1}),({x_2},{y_2}), \cdots ,({x_N},{y_N})\} $使得損失函式$\sum {L\left( {{y_i},{f_M}({x_i})} \right)} $最小化,即: $$\arg \mathop {\min }\limits_\Theta \sum\limits_{i = 1}^N {L\left( {{y_i},{f_M}({x_i})} \right)} = \arg \mathop {\min }\limits_\Theta \sum\limits_{i = 1}^N {L\left( {{y_i},\sum\limits_{m = 1}^M {T(x_i;{\Theta _m})} } \right)} \tag {2}$$ 在前面介紹Adaboost演算法博文中,我們說過,提升學習系列演算法採用前向分步演算法來迭代訓練個體學習器,提升樹當然也不例外,所以提升樹的迭代訓練過程可以表示為: $${f_m}(x) = {f_{m - 1}}(x) + T(x;{\Theta _m}),m = 1,2, \cdots ,M \tag {3}$$ 在這個迭代訓練過程中,每一次迭代都訓練完成一顆新的決策樹${T(x;{\Theta _m})}$,在這一過程中,也必須滿足總體損失函式最小化,也就是說,對於第$m$次迭代所確定的決策樹${T(x;{\Theta _m})}$的引數${{\Theta _m}}$有: $${{\hat \Theta }_m} = \arg \mathop {\min }\limits_\Theta \sum\limits_{i = 1}^N {L\left( {{y_i},{f_m}({x_i})} \right)} \tag {4}$$ 將式(3)代入式(4)中,有: $${{\hat \Theta }_m} = \arg \mathop {\min }\limits_\Theta \sum\limits_{i = 1}^N {L\left( {{y_i},{f_{m - 1}}({x_i}) + T({x_i};{\Theta _m})} \right)} \tag {5}$$

在提升樹演算法中,一般採用平方損失函式,於是: $$L\left( {{y_i},{f_{m - 1}}({x_i}) + T({x_i};{\Theta _m})} \right) = {\left[ {{y_i} - {f_{m - 1}}({x_i}) - T({x_i};{\Theta _m})} \right]^2} \tag {6}$$ 式(6)中,${{y_i} - {f_{m - 1}}({x_i})}$是上一輪迭代中預測值與真實值之間的偏差,這個偏差在提升樹中稱為殘差,用${{r_{m,i}}}$表示,於是式(6)可以表示為: $$L\left( {{y_i},{f_{m - 1}}({x_i}) + T({x_i};{\Theta _m})} \right) = {\left[ {{r_{m,i}} - T({x_i};{\Theta _m})} \right]^2} \tag {7}$$ 這就是第$m$次迭代訓練第$m$棵決策樹時的損失函式。可以看出,第$m$次迭代其實是對上一次迭代的殘差進行擬合,而不是類似Adaboost演算法中利用上一輪迭代中的誤差率來更新樣本權重,這就是提升樹演算法與Adaboost演算法的根本性區別。因此,每一次迭代結束後,提升樹演算法使用訓練樣本$x_i$與當前的殘差${{r_{m,i}}}$組成新的訓練樣本集${\{ (xi,{r_{m,i}})\} _{i = 1,2, \cdots ,N}}$來作為下一輪決策樹的訓練樣本集。

用一個例子來加深理解,假如要預測人的年齡,假設真實年齡為30歲,第一棵決策樹預測結果為20歲,那麼有10歲的殘差;第二棵樹對10歲的殘差進行擬合,輸出結果為6歲,有4歲的殘差;第3棵樹繼續對4歲的殘差進行擬合……重複這個過程,知道最終的殘差在可接受範圍,最終的輸出結果是每一棵樹的預測結果之和。
總結一下提升樹的流程:
輸入:資料集$D = \{ ({x_1},{y_1}),({x_2},{y_2}), \cdots ,({x_N},{y_N})\} $
(1)初始化個體學習器${f_0}(x) = 0$;
(2)進行$M$次迭代,其中第$m$次迭代的具體過程如下:
       (a)針對資料集$D$中每一個樣本$(x_i,y_i)$計算殘差${r_{m,i}} = {y_i} - {f_{m - 1}}({x_i})$;
       (b)利用${\{ (xi,{r_{m,i}})\} _{i = 1,2, \cdots ,N}}$來訓練一棵新的決策樹${T(x;{\Theta _m})}$;
       (c)更新組合:${f_m}(x) = {f_{m - 1}}(x) + T(x;{\Theta _m})$;
(3)對$M$次迭代獲得的$M$棵決策樹進行整合,得到最終的提升樹模型:${f_M}(x) = \sum\limits_{m = 1}^M {T(x;{\Theta _m})} $。

上述過程中,我們使用的是平方誤差作為損失函式,這時候對殘差的計算會比較簡單,但是在很多情況下,我們可能會使用其他的損失函式,這時候對殘差的計算就變得複雜起來。為了更好地解決這一問題這一問題,也就有了梯度提升樹。

 

3 梯度提升樹¶

從梯度提升樹這個演算法的名稱,我們容易想到梯度下降法,在我看來,梯度提升樹中確實也應用了梯度下降法的思想,在梯度下降法中是對模型的權重引數進行擬合,而在梯度提升樹中,是將整個決策樹模型作為引數進行擬合,可以證明,模型對梯度的負方向進行擬合,總能達到收斂的目的,而且是近似最速的方向,根據這一思想,Fredman提出了梯度提升演算法,梯度提升法的核心思想就是利用損失函式的負梯度在當前模型的具體值來替代提升樹演算法中的殘差來擬合一棵迴歸樹,使得提升樹思想在更加一般化的損失函式中也能快速優化求解,具有更高的適用性。
梯度提升法與提升樹演算法的結合,就是本篇的主角——梯度提升樹演算法。需要注意的是,在梯度提升樹中,無論是用於迴歸問題還是分類問題,所使用的的基學習演算法都是CART迴歸樹,區別在於所使用的的損失函式有所區別。
下面分別介紹梯度提升樹是如何解決迴歸問題和分類問題的。

3.1 迴歸問題¶

先來看看梯度提升樹演算法在解決迴歸問題時的步驟流程。
輸入:資料集$D = \{ ({x_1},{y_1}),({x_2},{y_2}), \cdots ,({x_N},{y_N})\} $
(1)初始化個體學習器 $${f_0}(x) = \arg \mathop {\min }\limits_c \sum\limits_{i = 1}^N {L\left( {{y_i},c} \right)} $$
(2)進行$M$次迭代,其中第$m$次迭代的具體過程如下:
       (a)針對資料集$D$中每一個樣本$(x_i,y_i)$計算負梯度在當前模型的值: $${r_{m,i}} = - {\left[ {\frac{{\partial L\left( {{y_i},f({x_i})} \right)}}{{\partial f({x_i})}}} \right]_{f(x) = {f_{m - 1}}(x)}}$$        (b)利用${\{ (xi,{r_{m,i}})\} _{i = 1,2, \cdots ,N}}$來訓練一棵新的迴歸樹$T({x_i};{\Theta _m}) = \sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{m,j}})} $;
       (c)對迴歸樹${T(x;{\Theta _m})}$確定其每一個葉節點${R_{m,j}},j = 1,2, \cdots ,J$上的最優輸出值${c_{m,j}}$:

$${c_{m,j}} = \arg \min \sum\limits_{{x_i} \in {R_{m,j}}} {L\left( {{y_i},{f_{m - 1}}({x_i}) + c} \right)} $$

       (d)更新組合:${f_m}(x) = {f_{m - 1}}(x) + \sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{m,j}})} $;
(3)對$M$次迭代獲得的$M$棵決策樹進行整合,得到最終的提升樹模型:${f_M}(x) = \sum\limits_{m = 1}^M {\sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{m,j}})} } $。

對比第2章節中的提升樹與本節講的梯度提升樹流程,可以發現,主要的區別就在於在提升提升樹中使用負梯度進行擬合而不再是殘差。另外,由於在梯度提升樹中損失函式不在限制於平方損失函式,因此在步驟(2)(c)中確定每一個葉節點上樣本輸出時,需要結合實際使用的損失函式來進行確定,例如當使用平方損失函式時,葉節點上的輸出值是該節點所有樣本的均值,當使用絕對值損失函式時,輸出值為該節點樣本的中位數。

3.2 分類問題¶

無論是分類問題還是迴歸問題,本質都是對損失函式進行優化,區別就在於使用何種損失函式。在多數分類演算法中,損失函式都是使用最大似然估計來構造,也包括本文的梯度提升樹。

 

(1)二分類問題
在二分類問題中,損失函式為:
$$L(y,f(x)) = \log \left( {1 + \exp ( - yf(x)} \right) \tag {8}$$ 對式(8)進行求導,可得負梯度: $${r_{mi}} = - {\left[ {\frac{{\partial L({y_i},f({x_i}))}}{{\partial f({x_i})}}} \right]_{f(x) = {f_{m - 1}}(x)}} = \frac{{{y_i}}}{{1 + \exp \left( {{y_i}f({x_i})} \right)}} \tag {9}$$ 在每一次迭代構建一棵決策樹時,都需要確定在每一個分支節點上的最優輸出值。第$m$棵決策樹的第$j$個節點輸出值為:
$${c_{mj}} = \arg \mathop {\min }\limits_c \sum\limits_{{x_i} \in {R_{mj}}} {\log \left( {1 + \exp ( - {y_i}({f_{m - 1}}({x_i}) + c))} \right)} \tag {10}$$ 一般而言,由於式(10)計算量比較大,難以優化,所以更多是通過下式來代替式(10):
$${c_{mj}} = \frac{{\sum\limits_{{x_i} \in {R_{mj}}} {{r_{mi}}} }}{{\sum\limits_{{x_i} \in {R_{mj}}} {\frac{{|{r_{mi}}|}}{{1 - |{r_{mi}}|}}} }} \tag {11}$$ 總結一下在二分類問題上,梯度提升樹演算法流程:
輸入:資料集$D = \{ ({x_1},{y_1}),({x_2},{y_2}), \cdots ,({x_N},{y_N})\} $ ,其中${y_i} \in \{ - 1, + 1\} $
(1)初始化個體學習器 $${f_0}(x) = \arg \mathop {\min }\limits_c \sum\limits_{i = 1}^N {L\left( {{y_i},p} \right)} $$
(2)進行$M$次迭代,其中第$m$次迭代的具體過程如下:
       (a)針對資料集$D$中每一個樣本$(x_i,y_i)$根據式(9)計算負梯度在當前模型的值${r_{mi}}$;
       (b)利用${\{ (x_i,{r_{mi}})\} _{i = 1,2, \cdots ,N}}$來訓練一棵新的迴歸樹$T({x_i};{\Theta _m}) = \sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{mj}})} $;
       (c)對迴歸樹${T(x;{\Theta _m})}$利用式(10)或者式(11)確定其每一個葉節點${R_{mj}},j = 1,2, \cdots ,J$上的最優輸出值${c_{mj}}$;
       (d)更新組合:${f_m}(x) = {f_{m - 1}}(x) + \sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{mj}})} $;
(3)對$M$次迭代獲得的$M$棵決策樹進行整合,得到最終的提升樹模型:${f_M}(x) = \sum\limits_{m = 1}^M {\sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{m,j}})} } $;
可以看出,出了負梯度計算和確定葉節點輸出值外,其他所有過程基本是和迴歸問題中的流程是一樣的。

 

(2)多分類問題 梯度提升樹演算法在處理多分類問題時過程要比處理二分類問題複雜一些。假設資料集樣本類別數量為$K$,則梯度提升樹演算法中損失函式可以表示為:
$$L(y,f(x)) = - \sum\limits_{k = 1}^K {{y_k}\log {p_k}(x)} \tag {12}$$ 其中,$p_k(x)$為樣本$x$屬於第$k$類的概率,有: $${p_k}(x){\text{ = }}\frac{{\exp \left( {{f_k}(x)} \right)}}{{\sum\limits_{l = 1}^K {\exp \left( {{f_l}(x)} \right)} }} \tag {13}$$ 結合式(12)(13)進行求導可得在第$m$次迭代時,第$i$個樣本在類別$l$上的負梯度為:
$${r_{mil}} = - {\left[ {\frac{{\partial L({y_i},f({x_i}))}}{{\partial f({x_i})}}} \right]_{{f_k}(x) = {f_{l,m - 1}}(x)}} = {y_{il}} - {p_{l,m - 1}}({x_i}) \tag{14}$$ 從式(14)可以看出,負梯度其實就是真實值與預測概率的差值。
確定每一個樹節點的輸出值:
$${c_{mjl}} = \arg \mathop {\min }\limits_{{c_{jl}}} \sum\limits_{i = 0}^m {\sum\limits_{k = 1}^K {L\left( {{y_k},{f_{m - 1}}_{,l}(x) + \sum\limits_{j = 0}^J {{c_{jl}}I({x_i} \in {R_{mjl}}} } \right)} } \tag {15}$$ 對於式(15),也有一個更加簡化的計算用於替代:
$${c_{mjl}} = \frac{{K - 1}}{K}\frac{{\sum\limits_{{x_i} \in {R_{mjl}}} {{r_{mil}}} }}{{\sum\limits_{{x_i} \in {R_{mil}}} {|{r_{mil}}|} (1 - |{r_{mil}}|)}} \tag {16}$$ 明白這些,就可以來梳理一下在多分類問題中,梯度提升樹演算法流程。
輸入:資料集$D = \{ ({x_1},{y_1}),({x_2},{y_2}), \cdots ,({x_N},{y_N})\} $
(1)初始化個體學習器 $${f_{k0}} = 0,k = 1,2, \ldots ,K$$ (2)進行$M$次迭代,其中第$m$次迭代的具體過程如下:
       (a)通過式(13)計算樣本點屬於每一個類別的概率;
       (b) 對$k = 1,2, \ldots ,K$進行迭代:
              1)通過式(14)計算負梯度;
              2)利用負梯度$\{ ({x_1},{r_{k1}}), \cdots ,({x_N},{r_{kN}})\} $擬合一棵決策樹;
              3)使用式(15)或(16)確定決策樹每一個節點上的輸出值;
              4)更新組合:${f_{mk}}(x) = {f_{m - 1,k}}(x) + \sum\limits_{j = 1}^J {{c_{mkj}}I(x \in {R_{mkj}})} $;
       (c)對迴歸樹${T(x;{\Theta _m})}$利用式(10)或者式(11)確定其每一個葉節點${R_{mj}},j = 1,2, \cdots ,J$上的最優輸出值${c_{mj}}$;
       (d)更新組合:${f_m}(x) = {f_{m - 1}}(x) + \sum\limits_{j = 1}^J {{c_{m,j}}I(x \in {R_{mj}})} $;
(3)得到最終的提升樹模型:${f_{Mk}}(x) = \sum\limits_{m = 1}^M {\sum\limits_{j = 1}^J {{c_{mkj}}I(x \in {R_{mkj}})} } $。
縱觀整個過程,其實無論是迴歸問題、二分類問題還是現在說的多分類問題,思路和流程都是基本一樣的。對於多分類問題,區別就在於對每一個類別都需要單獨建立一棵決策樹。上面的描述可能還不夠直觀,下面通過更加直白的描述來進一步分析多分類問題中的梯度提升樹演算法。
假設我們現在需要分類的資料集有3個類別標籤,即$k=3$,分別用$(A, B, C)$表示。在正式開始訓練之前,我們需要對每個樣本的類別標籤進行獨熱編碼轉換為向量的形式,例如,某個屬於第二個分類樣本$X=(x, B)$獨熱編碼轉換後類別可以用向量表示為[0, 1, 0],我們可以將向量每一個維度看做是屬於對應類別的概率,即第一位和第三位的0分別表示該樣本屬於第一個類別和第三類別的概率為0,第二位上的1表示該樣本屬於第二類的概率為1,這樣的話可以方便得將樣本$X$拆分為3個樣本:
$X_1=(x, 0)$表示樣本$x$屬於第1類的概率;
$X_2=(x, 1)$表示樣本$x$屬於第2類的概率;
$X_3=(x, 0)$表示樣本$x$屬於第3類的概率。

 

用這三個樣本,我們可以去訓練三棵迴歸樹,假設三棵樹的擬合值分別為${f_1}(x)$、${f_2}(x)$、${f_3}(x)$,通過式(13)可以將擬合值轉換為屬於三個類別的概率$p_1$、$p_2$、$p_3$,再通過式(14)求負梯度,即:
$${r_{111}} = 0 - {p_1}$$ $${r_{112}} = 0 - {p_2}$$ $${r_{113}} = 0 - {p_3}$$ 有了負梯度之後,可以繼續第二輪訓練,第二輪訓練時在第一輪的基礎上繼續訓練三棵樹,新的三棵樹分別用$(x,{r_{111}}$、$(x,{r_{112}}$、$(x,{r_{113}}$進行訓練。這一過程重複迭代$M$次,每次獲得3棵決策樹。最終我們可以獲得三個樹的整合,每個整合樹的最終輸出都對應一個類別的輸出。

 

4 總結¶

In [ ]: