XGBOOST(Extreme Gradient Boosting)算法原理詳細總結

        上篇我們對傳統的GBDT算法原理進行了探討,本篇我們來探討一個具有王者地位的算法:XGBOOST(Extreme Gradient Boosting
)。XGBOOST是來自於華盛頓大學的一個研究項目,2016年由陳天奇和Carlos Guestrin在KDD上發表:XGBoost: A Scalable Tree Boosting System。自此之後,XGBOOST不僅在kaggle比賽中贏得一席之地,而且也推動了工業領域的一些前沿應用的發展。XGBOOST是我們處理中小型結構化數據必須要掌握的一個殺手鐗。
        本篇我們主要參考陳天奇博士介紹XGBOOST的PPT:Boosted Trees

1)CART迴歸樹

        CART迴歸樹既可以處理分類任務又可以處理迴歸任務。CART算法對訓練樣本集的每個特徵遞歸的進行二分判斷,將特徵空間劃分爲有限的單元,每個單元具有一定的權重。簡單的可以認爲,CART迴歸樹是一個葉子節點具有權重的二叉決策樹。CART迴歸樹有兩個特點:

  • 決策規則和決策樹是一樣的;
  • 決策樹的每個葉子節點都包含一個權重;

下圖就是一個迴歸決策樹的示例:
在這裏插入圖片描述
        假如某決策樹的葉子節點數目爲TT,每個葉子節點的權重爲w={w1,w2,...wT}\overrightarrow{w}=\left\{w_1,w_2,...w_T\right\},樣本xx落在葉節點qq中,決策樹模型f(x)f(x)可以定義爲:
ft(x)=wq(x)ww,q:Rd{1,2,...T}f_t(x) = w_{q(x)} \quad w \in \overrightarrow{w},q:R^d\rightarrow \left\{1,2,...T\right\}
        從上式中可以看出,決策樹的兩個核心爲:樹的結構qq,葉節點的權重ww。確定樹的結構和葉節點的權重便可以確定一顆決策樹。
        在決策樹算法原理中我們瞭解到,決策樹比較容易過擬合,因此會對決策樹進行剪枝操作。那麼我們該如何衡量決策樹的複雜度呢?我們可以使用,樹的深度,葉節點數量,葉子節點權重的L2L2正則等。這裏我們使用葉節點的數量和葉子節點權重的L2L2正則表示決策樹模型的複雜度,數學表達式爲:
Ω(ft)=γT+12λj=1Twj2\Omega(f_t) =\gamma T+\frac{1}{2} \lambda \sum_{j=1}^Tw_j^2
其中,TT爲葉節點的個數,ww爲葉節點所對應的權重,γ\gamma爲收縮係數,λ\lambdaL2L2平滑係數。下圖即爲一個決策樹模型複雜度的示例:
在這裏插入圖片描述

2)XGBOOST目標函數

        XGBOOST基於Boosting框架,它採用的是前向優化算法,即從前往後,逐漸建立基模型來優化逼近目標函數,具體過程如下:
y^i(0)=0\hat y_i^{(0)}=0
y^i(1)=f1(xi)=y^i(0)+f1(xi)\hat y_i^{(1)}=f_1(x_i)=\hat y_i^{(0)} +f_1(x_i)
y^i(2)=f1(xi)+f2(xi)=y^i(1)+f2(xi)\hat y_i^{(2)}=f_1(x_i) + f_2(x_i)=\hat y_i^{(1)} +f_2(x_i)
......
y^i(t)=k=1tfk(xi)=y^i(t1)+ft(xi)\hat y_i^{(t)}=\sum_{k=1}^tf_k(x_i)=\hat y_i^{(t-1)} +f_t(x_i)
        從上式中,我們可以看出,每一步我們都是要訓練一個新的基模型ft(xi)f_t(x_i),那麼我們的目標就是讓訓練的新模型使得誤差最小,即目標函數爲:
Obj(t)=i=1nl(yi,y^i)+i=1tΩ(fi)Obj^{(t)}=\sum_{i=1}^nl(y_i,\hat y_i) +\sum_{i=1}^t\Omega(f_i)
=i=1nl(yi,y^i(t1)+ft(xi))+Ω(ft)+constant=\sum_{i=1}^nl(y_i,\hat y_i^{(t-1)} +f_t(x_i))+\Omega(f_t)+constant
其中Ω(ft)\Omega(f_t)爲模型複雜度,用來防止模型過擬合,平衡模型偏差和方差的。
        由泰勒二階展開式可知:
f(x+Δx)f(x)+f(x)Δx+12f(x)Δx2f(x+\Delta x)\approx f(x)+f'(x)\Delta x+\frac{1}{2}f''(x)\Delta x^2
        我們可以將y^i\hat y_i看出f(x+Δx)f(x+\Delta x)y^i(t1)\hat y_i^{(t-1)}即爲f(x)f(x)ft(xi)f_t(x_i)即爲Δx\Delta x,利用泰勒二階展開式,對目標函數進行近似展開得:
Obj(t)i=1n[l(yi,y^i(t1))+y^t1l(yi,y^i(t1))ft(xi)+12y^t12l(yi,y^i(t1))ft(xi)2]+Ω(ft)+constantObj^{(t)}\approx \sum_{i=1}^n[l(y_i,\hat y_i^{(t-1)})+\partial_{\hat y^{t-1}}l(y_i,\hat y_i^{(t-1)})f_t(x_i) +\frac{1}{2}\partial_{\hat y^{t-1}}^2l(y_i,\hat y_i^{(t-1)})f_t(x_i)^2]+\Omega(f_t)+constant
        爲了簡化目標函數,令gi=y^t1l(yi,y^i(t1)),hi=y^t12l(yi,y^i(t1))g_i=\partial_{\hat y^{t-1}}l(y_i,\hat y_i^{(t-1)}),h_i=\partial_{\hat y^{t-1}}^2l(y_i,\hat y_i^{(t-1)}),目標函數爲:
Obj(t)i=1n[l(yi,y^i(t1))+gift(xi)+12hift(xi)2]+Ω(ft)+constantObj^{(t)}\approx \sum_{i=1}^n[l(y_i,\hat y_i^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t(x_i)^2]+\Omega(f_t)+constant
=i=1n[gift(xi)+12hift(xi)2]+Ω(ft)+i=1nl(yi,y^i(t1))+constant=\sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t(x_i)^2]+\Omega(f_t)+ \sum_{i=1}^nl(y_i,\hat y_i^{(t-1)})+constant
        由於對於第tt步而言,y^i(t1)\hat y_i^{(t-1)}是一個已知數,所以i=1nl(yi,y^i(t1))\sum_{i=1}^nl(y_i,\hat y_i^{(t-1)})是一個常數,常數對於目標函數優化並無影響。因此,目標函數可以進一步簡化:
Obj(t)i=1n[gift(xi)+12hift(xi)2]+Ω(ft)Obj^{(t)}\approx\sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t(x_i)^2]+\Omega(f_t)
        由上一節討論CART決策樹模型爲:
ft(x)=wq(x)ww,q:Rd{1,2,...T}f_t(x) = w_{q(x)} \quad w \in \overrightarrow{w},q:R^d\rightarrow \left\{1,2,...T\right\}
        決策樹模型的複雜度可以表示爲:
Ω(ft)=γT+12λj=1Twj2\Omega(f_t) =\gamma T+\frac{1}{2} \lambda \sum_{j=1}^Tw_j^2
        現定義IjI_j表示第jj個葉子節點的樣本集合,即:
Ij={iq(xi)=j}I_j = \left\{i|q(x_i) = j\right\}
        現在我們使用每個葉子組合來重新表示目標函數:
Obj(t)i=1n[gift(xi)+12hift(xi)2]+Ω(ft)Obj^{(t)}\approx\sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t(x_i)^2]+\Omega(f_t)
=i=1n[giwq(xi)+12hiwq(xi)2]+γT+12λj=1Twj2= \sum_{i=1}^n[g_i w_{q(x_i)}+\frac{1}{2}h_iw_{q(x_i)}^2]+\gamma T+\frac{1}{2} \lambda \sum_{j=1}^Tw_j^2
=j=1T[(iIjgi)wj+12(iIjhi+λ)wj2]+γT=\sum_{j=1}^T[(\sum_{i \in I_j} g_i) w_j +\frac{1}{2}(\sum_{i \in I_j} h_i+\lambda)w_j^2]+\gamma T
        我們之前寫的目標函數是樣本的集合,現在都改寫成葉子結點的集合,由於一個葉子結點有多個樣本存在,因此纔有了iIjgi\sum_{i \in I_j} g_iiIjhi\sum_{i \in I_j} h_i這兩項。

3)XGBOOST目標函數優化

        由上節可知目標函數爲:
Obj(t)=j=1T[(iIjgi)wj+12(iIjhi+λ)wj2]+γTObj^{(t)}=\sum_{j=1}^T[(\sum_{i \in I_j} g_i) w_j +\frac{1}{2}(\sum_{i \in I_j} h_i+\lambda)w_j^2]+\gamma T
        我們定義Gj=iIjgi,Hj=iIjhiG_j=\sum_{i \in I_j} g_i,H_j=\sum_{i \in I_j} h_i,則目標函數可以寫成:
Obj(t)=j=1T[Gjwj+12(Hj+λ)wj2]+γTObj^{(t)}=\sum_{j=1}^T[G_j w_j +\frac{1}{2}(H_j+\lambda)w_j^2]+\gamma T
        我們回過頭來想想,如果一顆決策樹的結構已經確定,那麼每個葉子節點有哪些樣本也確定了,即Gj,HjG_j,H_j已知,但每個葉子節點的權重是不確定,即wjw_j不確定(我們要求的是wjw_j)。我們要求取目標函數最小值,那麼令目標函數一階導數爲0,得:
w=GjHj+λw^*=-\frac{G_j}{H_j+\lambda}
        將ww^*帶入目標函數得:
Obj(t)=12j=1TGj2Hj+λ+γTObj^{(t)}=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T
       上式越小,樹的結構就越好。下圖便能直觀的展示目標函數的計算過程。

在這裏插入圖片描述

4)子樹ftf_t的生成

        對於XGBOOST單顆子樹的生成,你可能會想到使用枚舉法:

  1. 枚舉所有可能存在的樹的結構qq;
  2. 計算所有樹的目標函數的得分;
    Obj(t)=12j=1TGj2Hj+λ+γTObj^{(t)}=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T
  3. 確定目標函數最小的樹,求個葉子節點的最優權重;
    w=GjHJ+λw^*=-\frac{G_j}{H_J+\lambda}

        但樹的結構有無限可能,無法枚舉,需要換一種方式。另一種方式是,使用貪婪算法。

  1. 從樹的深度爲0開始,每一節點都遍歷所有的特徵;
  2. 對於某一個特徵,先對特徵的值進行升序排序,分別計算特徵的各取值對應的obj=12j=1TGj2Hj+λ+γTobj=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T。在所有的特徵取值中,選擇objobj降低最小的特徵值作爲分裂點,最後在所有的特徵裏,選擇分割後Gain最高的特徵作爲當前節點分割特徵。Gain計算過程如下:Obj(nosplit)=12j=1t(GL+GR)2HL+HR+λ+γTObj_{(nosplit)}=-\frac{1}{2}\sum_{j=1}^t\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}+\gamma T
    Obj(split)=12j=1tGL2HL+λ12j=1tGR2HR+λ+γ(T+1)Obj_{(split)}=-\frac{1}{2}\sum_{j=1}^t\frac{G_L^2}{H_L+\lambda}-\frac{1}{2}\sum_{j=1}^t\frac{G_R^2}{H_R+\lambda}+\gamma(T+1)
    Obj(nosplit)Obj(split)=12j=1t(GL+GR)2HL+HR+λ+γT+12j=1tGL2HL+λ+12j=1tGR2HR+λγ(T+1)Obj_{(nosplit)}-Obj_{(split)}=-\frac{1}{2}\sum_{j=1}^t\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}+\gamma T+\frac{1}{2}\sum_{j=1}^t\frac{G_L^2}{H_L+\lambda}+\frac{1}{2}\sum_{j=1}^t\frac{G_R^2}{H_R+\lambda}-\gamma(T+1)
    =12[j=1tGR2HR+λ+j=1tGL2HL+λj=1t(GL+GR)2HL+HR+λ]γ=-\frac{1}{2}[\sum_{j=1}^t\frac{G_R^2}{H_R+\lambda}+\sum_{j=1}^t\frac{G_L^2}{H_L+\lambda}-\sum_{j=1}^t\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}]-\gamma
  3. 遞歸執行上式步驟,直到樹的最大的深度,然後進行剪枝,遞歸得把劃分葉子得到的Gain爲負的剪枝。

貪婪算法子樹生成的算法過程如下(不包含剪枝部分):
在這裏插入圖片描述

5)XGBOOST算法過程

        下面我們看看XGBOOST具體的算法過程:
輸入:訓練數據集D={(xi,yi)}i=1nD=\left\{ (x_i,y_i) \right\}^n_{i=1}xiRdx_i\in R^d,最大迭代次數TT
輸出:強學習器h(x)h(x)

  • for t=1,2....TT:for \ t=1,2....T(迭代T次):
    • 計算所有樣本的一階導數Gj=i=1ngiG_j=\sum_{i =1}^n g_i,二階導數Hj=i=1nhiH_j=\sum_{i =1}^n h_i
    • 採用貪婪法生成子樹ft(x)f_t(x),計算每個葉子節點Gi,HiG_i,H_i,並求取每個葉子節點的權重ww^*
    • 把新生成的決策樹ft(x)f_t(x)加入y^i(t)=y^i(t1)+ϵft(xi)\hat y_i^{(t)} =\hat y_i^{(t-1)} +\epsilon f_t(x_i) ,其中 ϵ\epsilon爲學習率,主要爲了控制模型的過擬合。
  • h(x)=t=1Tft(xi)h(x)=\sum_{t=1}^Tf_t(x_i)

6)XGBOOST算法總結

        下面我們對XGBOOST算法的特點進行總結。
算法改進:

  • 目標函數引入了正則項Ω(f)\Omega(f)
  • 算法內置了交叉驗證功能;
  • 能自動對缺失值進行處理;
  • 可自定義目標函數,只需滿足有二階導數;

系統優化:

  • 並行計算各個特徵的增益;
  • 剪枝,先按照最大深度進行子樹生成,再進行遞歸剪枝;
  • 硬件優化,通過設置合理的分塊的大小,充分利用了CPU緩存進行讀取加速;

        由此可以看出,XGBOOST在GBDT上做的優化已接近極致。因此,後續微軟推出的LightGBM也是隻在內存佔用和運行速度做了不少優化。如果你使用XGBOOST算法,內存佔用和運行速度成了問題,選擇使用LightGBM是一個不錯的選擇。
        下篇我們探討scikit-learn中XGBOOST的使用。

(歡迎大家在評論區探討交流,也歡迎大家轉載,轉載請註明出處!)

上篇:Scikit-learn GBDT算法庫總結與實踐
下篇:持續更新中,敬請關注

發佈了17 篇原創文章 · 獲贊 55 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章