XGBoost基本原理

香橙雲子發表於2017-11-22

XGBoost的實現,我覺得主要還是在於對GBDT的改良上。對於GBDT還是不太熟悉的朋友,請看我這一篇文章《GBDT》。我個人認為這兩者區別主要還是在於細節上,理解了GBDT我認為就差不多等於理解了XGBoost。

我重點比較一下XGBoost與GBDT兩種演算法的不同:

XGBoost的目標函式與GBDT存在泰勒展開項的不同:

最基本的差距就在於XGBoost比GBDT多了兩項泰勒展開式。具體這個泰勒展開式是怎麼得到的,是對於什麼展開的呢?我們看:
XGBoost演算法可以看成是由K棵樹組成的加法模型:

XGBoost加法模型
XGBoost加法模型

其中F為所有樹組成的函式空間(這裡的迴歸樹也就是一個分段函式,不同分段的不同取值就構成了一顆樹),與一般機器學習演算法不同的是,加法模型不是學習d維空間的權重,而是直接學習決策樹的集合。
上述加法模型的目標函式定義為:

目標函式
目標函式

其中Ω表示決策樹的複雜度,那麼該如何定義樹的複雜度呢?比如,可以考慮樹的節點數量、樹的深度或者葉子節點所對應的分數的L2範數等等。
如何來學習加法模型呢?
解這一優化問題,可以用前向分佈演算法(forward stagewise algorithm)。有了之前GBDT的基礎,我們知道,加法模型的學習器每次都用函式來擬合上一棵樹沒有擬合完整的殘差,最後將這些殘差全部加起來就會得到對於目標完整的預測,這也叫做Boosting。具體地,我們從一個常量預測開始,每次學習一個新的函式,過程如下:

加法學習器的Boosting
加法學習器的Boosting

這個公式看起來還是比較拗口,想要理解的話建議看我之前的文章《GBDT》,瞭解了工作模式這公式就好理解了。

這就會產生一個新的問題,那個新加入的函式f到底怎麼得到的呢?這個原則還是最小化目標函式。我們可以將我們的目標函式寫為:

目標函式變式
目標函式變式

我們再用平方誤差來衡量我們的損失函式:

平方誤差衡量損失函式
平方誤差衡量損失函式

其中 XGBoost基本原理就是我們所謂的殘差(residual)。我們每一次使用平方函式的時候,演算法都是為了擬合這個殘差。
可能有的朋友對於泰勒公式不是非常熟悉,我將基本的泰勒公式用法寫在這:

泰勒公式基本形式
泰勒公式基本形式

我們都知道,泰勒級數展開其實是有無窮多項的,在無窮多項形式裡是嚴格等於,這裡我們暫且只取了前三項省略了後面,所以就是約等於。
那有了泰勒公式的基礎,我們將前面的目標函式變式可以轉化為:

目標函式泰勒級數展開三項
目標函式泰勒級數展開三項

其中,g與h分別是損失函式的一階偏導數和二階偏導數,具體數學形式如下:

泰勒展開的一次微分項與二次微分項
泰勒展開的一次微分項與二次微分項

我們也可以將常數項直接去掉,並不會影響,那就使得目標函式是這個樣子:

去掉常數項的目標函式
去掉常數項的目標函式

由於要學習的函式僅僅依賴於目標函式,從“去掉常數項的目標函式”可以看出只需為學習任務定義好損失函式,併為每個訓練樣本計算出損失函式的一階導數和二階導數,通過在訓練樣本集上最小化目標函式即可求得每步要學習的函式,從而根據加法模型可得最終要學習的模型。

GBDT的目標函式
GBDT的目標函式

就簡單提一句GBDT與XGBoost的區別,明顯可以看出,GBDT沒有采用二次泰勒展開,這個看似很簡單的區別,實際上帶來更快的擬合,也大大縮減了生成樹的規模,減少了執行時間。

XGBoost相比於GBDT加入了正則化項(Regularization)

我們使用損失函式優化是為了避免欠擬合,而使用正則化項就是為了避免過擬合。正則化項與損失函式共同組成了我們的目標函式。XGBoost比GBDT多新增了以樹複雜度構成的正則化項,也是XGBoost實際表現更為優秀的原因之一

何為正則化項?正則化項的作用是什麼?
我們都知道,我們在優化目標函式的時候,總是希望它更加的“小”,也就是優化一般是最小化的意思。現在我們如果給目標函式加入一個變數的平方,那麼如果這個變數一旦變大,那麼目標函式為了“最小化”,一定很不喜歡這個變數變大的事實,選擇的時候就會刻意避開會使變數變大的路徑。這大概就是正則化的簡單解釋了。在XGBoost中,我們是將樹的複雜度作為正則項加入,那麼優化器在工作的時候,會盡量不讓這個樹更加複雜,也就達到我們的效果。

我們假設XGBoost決策樹的葉子節點個數為T,該決策樹是由所有葉子節點對應的值組成的向量w,以及一個把特徵向量對映到葉子節點索引(Index)的函式 XGBoost基本原理組成的,我們將樹可以寫成:
XGBoost基本原理,我們也可以將決策樹的複雜度定義成正則項:

決策樹複雜度定義的正則化項
決策樹複雜度定義的正則化項

則目標函式我們可以寫成:

完整正則項的目標函式
完整正則項的目標函式

用G與H代換一下原來的式子,我們就得到了簡化後的式子:

簡化後的目標函式
簡化後的目標函式

假設樹的結構是固定的,即函式q(x)為固定的,令目標函式的一階導數為0,則可以求出葉子節點j對應的值為:

葉子節點j對應的值
葉子節點j對應的值

於是在這種條件下,目標函式的值就變成了:

目標函式的值
目標函式的值

為什麼要計算這兩個值呢?
是為了給大家描述單棵決策樹的生成過程:

  1. 列舉所有可能的樹的結構q
  2. 用目標函式值為每個q計算對應的分數Obj,分數越小說明結構越好
  3. 根據上一步結果,找到分數最小的子節點,生成新的分支,併為每個子節點計算預測值

XGBoost的分裂增益與GBDT的比較

樹結構數量是無窮的,所以實際上我們不可能列舉所有可能的樹結構。通常情況下,我們採用貪心策略來生成決策樹的每個節點。

我們來看看這個貪心演算法是怎麼工作的:

  1. 從深度為0的樹開始,對每個葉節點列舉所有的可用特徵
  2. 針對每個特徵,把屬於該節點的訓練樣本根據該特徵值升序排列,通過線性掃描的方式來決定該特徵的最佳分裂點,並記錄該特徵的最大收益(採用最佳分裂點時的收益)
  3. 選擇收益最大的特徵作為分裂特徵,用該特徵的最佳分裂點作為分裂位置,把該節點生長出左右兩個新的葉節點,併為每個新節點關聯對應的樣本集
  4. 回到第1步,遞迴執行到滿足特定條件為止

如何計算每次分裂的收益呢?假設當前節點記為C,分裂之後左孩子節點記為L,右孩子節點記為R,則該分裂獲得的收益定義為當前節點的目標函式值減去左右兩個孩子節點的目標函式值之和:Gain=ObjC-ObjL-ObjR,具體地,根據目標函式值公式可得:

XGBoost的增益
XGBoost的增益

相關文章