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