XGBoost-原理推导(上)
XGBoost簡介
XGBoost(eXtreme Gradient Boosting)是華盛頓大學博士陳天奇創造的一個梯度提升(Gradient Boosting)的開源框架。至今可以算是各種數據比賽中的大殺器,被大家廣泛地運用。
之前的文章我已經介紹了GBDT,如果對GBDT原理不太懂的,強烈建議先把GBDT的原理搞清楚再回過頭來看XGBoost,接下來我會分上中下三篇文章詳細介紹XGBoost,包括目標函數,學習策略,重要超參數,系統設計,優缺點等。
目標函數
我們知道 XGBoost 是由 K 個基模型組成的一個加法運算式:
其中fkf_kfk?表示第kkk個模型,y^i\widehat{y}_iy?i?為第iii個樣本的預測值。
損失函數可由預測值 y^i\widehat{y}_iy?i? 與真實值 yiy_iyi? 進行表示:
我們知道模型的預測精度由模型的偏差和方差共同決定,損失函數代表了模型的偏差,想要方差小則需要簡單的模型,所以目標函數由模型的損失函數 LLL 與抑制模型復雜度的正則項 Ω\OmegaΩ 組成,所以我們有:
Ω\OmegaΩ 為模型的正則項,由于 XGBoost 支持決策樹也支持線性模型,所以這里再不展開描述。
我們知道 boosting 模型是前向加法,以第 ttt 步的模型為例,模型對第 iii 個樣本 xix_ixi? 的預測為:
其中 y^it?1\widehat{y}^{t-1}_iy?it?1? 由第 t?1t-1t?1 步的模型給出的預測值,是已知常數,ft(xi)f_t(x_i)ft?(xi?) 是我們這次需要加入的新模型的預測值,此時,目標函數就可以寫成:
求此時最優化目標函數,就相當于求解 ft(xi)f_t(x_i)ft?(xi?) 。
根據泰勒公式我們把函數 f(x+Δx)f(x+\Delta x)f(x+Δx) 在點 xxx 處進行泰勒的二階展開,可得到如下等式:
我們把 y^it?1\widehat{y}^{t-1}_iy?it?1? 視為 xxx, ft(xi)f_t(x_i)ft?(xi?) 視為 Δx\Delta xΔx ,故可以將目標函數寫為:
其中 gig_igi? 為損失函數的一階導, hih_ihi? 為損失函數的二階導,注意這里的導是對 y^it?1\widehat{y}^{t-1}_iy?it?1? 求導。
我們以平方損失函數為例:
則:
由于在第 ttt 步時 y^it?1\widehat{y}^{t-1}_iy?it?1? 其實是一個已知的值,所以 l(yi,y^it?1)l(y_i,\widehat{y}^{t-1}_i)l(yi?,y?it?1?) 是一個常數,其對函數的優化不會產生影響,因此目標函數可以寫成:
所以我們只需要求出每一步損失函數的一階導和二階導的值(由于前一步的 y^t?1\widehat{y}^{t-1}y?t?1 是已知的,所以這兩個值就是常數),然后最優化目標函數,就可以得到每一步的 f(x)f(x)f(x) ,最后根據加法模型得到一個整體模型。
注意:其實推導到這里我們還可以將上式子進一步簡化,式子中的第二項是每個基學習器求和的結果,前面的 t?1t-1t?1 個學習器是已知的,所以正則化的前 t?1t-1t?1 項也是已知的,可以看作一個常數。
基于決策樹的目標函數
我們知道 Xgboost 的基模型不僅支持決策樹,還支持線性模型,這里我們主要介紹基于決策樹的目標函數。
xxx 為某一樣本,這里的 q(x)q(x)q(x) 代表了該樣本在哪個葉子結點上,而 wqw_qwq? 則代表了葉子結點取值 www ,所以 wq(x)w_{q(x)}wq(x)? 就代表了每個樣本的取值 www(即預測值)。
決策樹的復雜度可由葉子數 TTT 組成,葉子節點越少模型越簡單,此外葉子節點也不應該含有過高的權重 www (類比 LR 的每個變量的權重),所以目標函數的正則項可以定義為:
即決策樹模型的復雜度由生成的所有決策樹的葉子節點數量,和所有節點權重所組成的向量的 L2L2L2 范式共同決定。
這張圖給出了基于決策樹的 XGBoost 的正則項的求解方式。
我們設 Ij={i∣q(xi)=j}I_j = \{i\mid q(x_i) = j\}Ij?={i∣q(xi?)=j} 為第 jjj 個葉子節點的樣本集合,故我們的目標函數可以寫成:
第二步到第三步可能看的不是特別明白,這邊做些解釋:第二步是遍歷所有的樣本后求每個樣本的損失函數,但樣本最終會落在葉子節點上,所以我們也可以遍歷葉子節點,然后獲取葉子節點上的樣本集合,最后在求損失函數。即我們之前樣本的集合,現在都改寫成葉子結點的集合,由于一個葉子結點有多個樣本存在,因此才有了 ∑i∈Ijgi\sum_{i\in I_j}g_i∑i∈Ij??gi?和 ∑i∈Ijhi\sum_{i\in I_j}h_i∑i∈Ij??hi? 這兩項,wjw_jwj? 為第 jjj 個葉子節點取值。
為簡化表達式,我們定義 Gj=∑i∈IjgiG_j = \sum_{i\in I_j}g_iGj?=∑i∈Ij??gi? , Hj=∑i∈IjhiH_j = \sum_{i\in I_j}h_iHj?=∑i∈Ij??hi? ,則目標函數為:
這里我們要注意 GjG_jGj? 和 HjH_jHj? 是前 t?1t-1t?1 步得到的結果,其值已知可視為常數,只有最后一棵樹的葉子節點 wjw_jwj? 不確定,那么將目標函數對 wjw_jwj? 求一階導,并令其等于 000 ,則可以求得葉子結點 jjj 對應的權值:
所以目標函數可以化簡為:
上圖給出目標函數計算的例子,求每個節點每個樣本的一階導數 gig_igi? 和二階導數 hih_ihi? ,然后針對每個節點對所含樣本求和得到的 GiG_iGi? 和 HiH_iHi? ,最后遍歷決策樹的節點即可得到目標函數。
到了這里,大家可能已經注意到了,比起最初的損失函數 + 復雜度的樣子,我們的目標函數已經發生了巨大變化。我們的樣本量已經被歸結到了每個葉子當中去,我們的目標函數是基于每個葉子節點,也就是樹的結構來計算。所以,我們的目標函數又叫做“結構分數”(structure score),分數越低,樹整體的結構越好。如此,我們就建立了樹的結構(葉子)和模型效果的直接聯系。
最優切分點劃分算法
在決策樹的生長過程中,一個非常關鍵的問題是如何找到葉子的節點的最優切分點,Xgboost 支持兩種分裂節點的方法——貪心算法和近似算法。
1.貪心算法
貪心算法指的是控制局部最優來達到全局最優的算法,決策樹算法本身就是一種使用貪婪算法的方法。XGB作為樹的集成模型,自然也想到采用這樣的方法來進行計算,所以我們認為,如果每片葉子都是最優,則整體生成的樹結構就是最優,如此就可以避免去枚舉所有可能的樹結構
回憶一下決策樹中我們是如何進行計算:我們使用基尼系數或信息熵來衡量分枝之后葉子節點的不純度,分枝前的信息熵與分治后的信息熵之差叫做信息增益,信息增益最大的特征上的分枝就被我們選中,當信息增益低于某個閾值時,就讓樹停止生長。在XGB中,我們使用的方式是類似的:我們首先使用目標函數來衡量樹的結構的優劣,然后讓樹從深度0開始生長,每進行一次分枝,我們就計算目標函數減少了多少,當目標函數的降低低于我們設定的某個閾值時,就讓樹停止生長。
具體步驟:
那么如何計算每個特征的分裂收益呢?
假設我們在某一節點完成特征分裂,則分列前的目標函數可以寫為:
分裂后的目標函數為:
則對于目標函數來說,分裂后的收益為:
注意該特征收益也可作為特征重要性輸出的重要依據。對于每次分裂,我們都需要枚舉所有特征可能的分割方案,如何高效地枚舉所有的分割呢?
我假設我們要枚舉所有 x<ax<ax<a 這樣的條件,對于某個特定的分割點 aaa 我們要計算 aaa 左邊和右邊的導數和。
我們可以發現對于所有的分裂點 aaa ,我們只要做一遍從左到右的掃描就可以枚舉出所有分割的梯度和 GLG_LGL? 和 GRG_RGR? 。然后用上面的公式計算每個分割方案的分數就可以了。
CART樹全部是二叉樹,因此這個式子是可以推廣的。從這個式子我們可以總結出,其實分枝后的結構分數之差為:
其中 GLG_LGL? 和 HLH_LHL? 從左節點上計算得出, GRG_RGR? 和 HRH_RHR? 從右節點上計算得出,而 (GL+GR)(G_L + G_R)(GL?+GR?) 和 (HL+HR)(H_L + H_R)(HL?+HR?) 從中間節點上計算得出。對于任意分枝,我們都可以這樣來進行計算。
在現實中,我們會對所有特征的所有分枝點進行如上計算,然后選出讓目標函數下降最快的節點來進行分枝。對每一棵樹的每一層,我們都進行這樣的計算,比起原始的梯度下降,實踐證明這樣的求解最佳樹結構的方法運算更快,并且在大型數據下也能夠表現不錯。至此,我們作為XGBoost的使用者,已經將需要理解的XGB的原理理解完畢了。
2.近似算法
貪婪算法可以的到最優解,但當數據量太大時則無法讀入內存進行計算,近似算法主要針對貪婪算法這一缺點給出了近似最優解。
對于每個特征,只考察分位點可以減少計算復雜度。
該算法會首先根據特征分布的分位數提出候選劃分點,然后將連續型特征映射到由這些候選點劃分的桶中,然后聚合統計信息找到所有區間的最佳分裂點。
在提出候選切分點時有兩種策略:
Global:學習每棵樹前就提出候選切分點,并在每次分裂時都采用這種分割;
Local:每次分裂前將重新提出候選切分點。
直觀上來看,Local 策略需要更多的計算步驟,而 Global 策略因為節點沒有劃分所以需要更多的候選點。
下圖給出不同種分裂策略的 AUC 變換曲線,橫坐標為迭代次數,縱坐標為測試集 AUC,eps 為近似算法的精度,其倒數為桶的數量。
我們可以看到 Global 策略在候選點數多時(eps 小)可以和 Local 策略在候選點少時(eps 大)具有相似的精度。此外我們還發現,在 eps 取值合理的情況下,分位數策略可以獲得與貪婪算法相同的精度。
第一個 for 循環:對特征 k 根據該特征分布的分位數找到切割點的候選集合 Sk={sk1,sk2,...,skl}S_k = \{ s_{k1},s_{k2},...,s_{kl}\}Sk?={sk1?,sk2?,...,skl?} 。XGBoost 支持 Global 策略和 Local 策略。
第二個 for 循環:針對每個特征的候選集合,將樣本映射到由該特征對應的候選點集構成的分桶區間中,即 sk,v≥xjk≥sk,v?1s_{k,v} \geq x_{jk} \geq s_{k,v-1}sk,v?≥xjk?≥sk,v?1? ,對每個桶統計 G,HG,HG,H 值,最后在這些統計量上尋找最佳分裂點。
下圖給出近似算法的具體例子,以三分位為例:
根據樣本特征進行排序,然后基于分位數進行劃分,并統計三個桶內的 [公式] 值,最終求解節點劃分的增益。
加權分位數縮略圖
事實上, XGBoost 不是簡單地按照樣本個數進行分位,而是以二階導數值 [公式] 作為樣本的權重進行劃分,如下:
那么問題來了:為什么要用 hih_ihi? 進行樣本加權?
我們知道模型的目標函數為:
我們稍作整理,便可以看出 hih_ihi? 有對 loss 加權的作用。
其中 121\over221?gi2hig_i^2\over h_ihi?gi2?? 與 CCC 皆為常數。我們可以看到 hih_ihi? 就是平方損失函數中樣本的權重。
對于樣本權值相同的數據集來說,找到候選分位點已經有了解決方案(GK 算法),但是當樣本權值不一樣時,該如何找到候選分位點呢?(作者給出了一個 Weighted Quantile Sketch 算法,這里將不做介紹。)
稀疏感知算法
在決策樹的第一篇文章中我們介紹 CART 樹在應對數據缺失時的分裂策略,XGBoost 也給出了其解決方案。
XGBoost 在構建樹的節點過程中只考慮非缺失值的數據遍歷,而為每個節點增加了一個缺省方向,當樣本相應的特征值缺失時,可以被歸類到缺省方向上,最優的缺省方向可以從數據中學到。至于如何學到缺省值的分支,其實很簡單,分別枚舉特征缺省的樣本歸為左右分支后的增益,選擇增益最大的枚舉項即為最優缺省方向。
在構建樹的過程中需要枚舉特征缺失的樣本,乍一看該算法的計算量增加了一倍,但其實該算法在構建樹的過程中只考慮了特征未缺失的樣本遍歷,而特征值缺失的樣本無需遍歷只需直接分配到左右節點,故算法所需遍歷的樣本量減少,下圖可以看到稀疏感知算法比 basic 算法速度塊了超過 50 倍。
總結
以上是生活随笔為你收集整理的XGBoost-原理推导(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生山药的功效与作用、禁忌和食用方法
- 下一篇: 胎菊花茶的功效与作用、禁忌和食用方法