從XGboost到lightGBM

XGboost

XGBoost是GBDT的一種高效實現,但是裏面也加入了很多獨有的思路和方法

我們先回顧一下CART迴歸樹

CART迴歸樹

CART迴歸樹是假設樹的結構爲二叉樹,通過不斷將特徵進行分裂去完成整個樹的構建。比如當前樹結點是基於第j個特徵值進行分裂的,設該特徵值小於s的樣本劃分爲左子樹,大於s的樣本劃分爲右子樹,即
R1(j,s)={xx(j)s}  and   R2(j,s)={xx(j)>s}R_1(j,s)=\begin{Bmatrix}x|x^{(j)}\leq s \end{Bmatrix}\,\, and \,\,\, R_2(j,s)=\begin{Bmatrix}x|x^{(j)}> s \end{Bmatrix}

其實質就是在該特徵維度上對樣本空間進行劃分,這種劃分是非常複雜度,通常是NP難問題。因此,在決策樹模型中是使用啓發式方法解決特徵劃分問題。

典型CART迴歸樹模型的目標函數爲:

L=xiRm(yif(xi))2L=\sum_{x_i\in R_m}(y_i-f(x_i))^2

我們結合求解最優的切分特徵j和最優的切分點s,那麼目標函數就轉化爲求解如下式子:
minj,s[minc1xiR1(j,s)(yic1)2+minc2xiR2(j,s)(yic2)2]\underbrace{min}_{j,s}\left[\underbrace{min}_{c_1}\sum_{x_i\in R_1(j,s)}(y_i-c_1)^2+\underbrace{min}_{c_2}\sum_{x_i\in R_2(j,s)}(y_i-c_2)^2\right]

XGBoost算法原理

XGBoost算法思想就是不斷地添加樹,不斷地進行特徵分裂來完成一棵樹的構建。每次添加一個樹,實際上是學習一個新函數,去擬合上次預測的殘差。我們訓練完成時會得到k棵樹 。當我們要預測一個樣本的分數時,根據這個樣本的特徵,在每棵樹中會落到對應的一個葉子節點,每個葉子節點就對應一個分數,最後只需要將每棵樹對應的分數加起來就是該樣本的預測值。如:
y^=ϕ(xi)=k=1Mfk(xi)  where  F={f(x)=wq(x)}(q:RmT,wRnT)\hat{y}=\phi(x_i)=\sum_{k=1}^Mf_k(x_i) \,\,where\,\, F=\begin{Bmatrix}f(x)=w_{q(x)} \end{Bmatrix}(q:R^m\rightarrow T,w\in R_n^T)

注:Wq(x)爲葉子節點q的分數–可以理解爲權重,f(x)爲其中一棵迴歸樹 。

損失函數

XGBoost目標函數定義爲:L=i=1nl(yi,yi^)+k=1KΩ(fk)L=\sum_{i=1}^nl(y_i,\hat{y_i})+\sum_{k=1}^K\Omega (f_k)
目標函數由兩部分構成,第一部分用來衡量預測分數和真實分數的差距,另一部分​則是正則化項。

正則化項同樣包含兩部分,Ω(f)=rT+12λw2\Omega (f)=r T+\frac12\lambda ||w||^2
T表示葉子結點的個數,w表示葉子節點的分數。r可以控制葉子結點的個數,λ\lambda可以制葉子節點的分數不會過大,防止過擬合。
新生成的樹是要擬合上次預測的殘差的,即當生成t棵樹後,預測分數可以寫成:yi^(t)=yi^(t1)+ft(xi)\hat{y_i}^{(t)}=\hat{y_i}^{(t-1)}+f_t(x_i)
同時,可以將目標函數改寫成: L=i=1nl(yi,yi^(t1)+ft(xi))+k=1KΩ(fk)L=\sum_{i=1}^nl(y_i,\hat{y_i}^{(t-1)}+f_t(x_i))+\sum_{k=1}^K\Omega (f_k)

很明顯,我們接下來就是要去找到一個ftf_t能夠最小化目標函數。XGBoost的想法是利用其在ftf_t=0處的泰勒二階展開近似它。即f(x+Δx)f(x)+f(x)Δx+(12f(x)Δx2)f(x+\Delta x)\approx f(x)+f\prime(x)\Delta x+(\frac12f\prime\prime(x)\Delta x^2)

g一階導數,h 爲二階導數:
gi=y^(t1)l(yi,yi^(t1))g_i=\partial_{\hat{y}^{(t-1)}}l(y_i,\hat{y_i}^{(t-1)})
hi=y^(t1)2l(yi,yi^(t1))h_i=\partial_{\hat{y}^{(t-1)}}^2l(y_i,\hat{y_i}^{(t-1)})

目標函數近似爲:

L(t)=i=1n[l(yi,yi^(t1))+gift(xi)+12hift2(xi)]+Ω(ft)L^{(t)}=\sum_{i=1}^n\left[ l(y_i,\hat{y_i}^{(t-1)})+g_if_t(x_i)+\frac12h_if_t^2(x_i) \right]+\Omega (f_t)

以上這就是XGboost的特點:通過這種近似,可以自行定義一些損失函數(例如,平方損失,邏輯損失),只需要保證二階可導即可。由於前t-1棵樹的預測分數的殘差對目標函數優化不影響[因爲t輪是在之前殘差基礎上進行預測,所以可以看作是常數],可以直接去掉。簡化目標函數爲:
L(t)=i=1n[gift(xi)+12hift2(xi)]+Ω(ft)L^{(t)}=\sum_{i=1}^n\left[ g_if_t(x_i)+\frac12h_if_t^2(x_i) \right]+\Omega (f_t)

上式是將每個樣本的損失函數值加起來,我們知道,每個樣本都最終會落到一個葉子結點中,所以我們可以將所以同一個葉子結點的樣本重組起來,過程如下:

L(t)L^{(t)}
=i=1n[gift(xi)+12hift2(xi)]+Ω(ft)=\sum_{i=1}^n\left[ g_if_t(x_i)+\frac12h_if_t^2(x_i) \right]+\Omega (f_t)

=j=1T[giwq(xi)+12hiwq(xi)2]+rT+12λj=1Twj2=\sum_{j=1}^T\left[ g_iw_{q(x_i)}+\frac12h_iw_{q(x_i)}^2 \right]+r T+\frac12\lambda \sum_{j=1}^Tw_j^2

=j=1T[(iIjgi)wj+12(iIjhi+λ)wj2]+rT=\sum_{j=1}^T\left[ (\sum_{i\in I_j}g_i)w_j+\frac12(\sum_{i\in I_j}h_i+\lambda)w_j^2 \right]+r T

前兩步i=1 to n 其實是對於每一個樣本來說,進行遍歷
最後一步直接把樣本放在葉子結點的結果中去計算,這樣可以便於進行計算

因此通過上式的改寫,我們可以將目標函數改寫成關於葉子結點分數w的一個一元二次函數,求解最優的和目標函數值就變得很簡單了。

對於一個固定的結構q(x) ,我們可以計算葉節點j的最優權重wjw_j

即對w求導,令其等於0

wj=iIjgiiIjhi+λw_j^*=-\frac{\sum_{i\in I_j}g_i}{\sum_{i\in I_j}h_i+\lambda}

帶入可以計算相應的最優損失函數
L(t)(q)=12j=1T(iIjgi)2iIjhi+λ+rTL^{(t)}(q)=-\frac12\sum_{j=1}^T\frac{(\sum_{i\in I_j}g_i)^2}{\sum_{i\in I_j}h_i+\lambda}+r T

分裂結點算法在上面的推導中,我們知道了如果我們一棵樹的結構確定了,如何求得每個葉子結點的分數。但我們還沒介紹如何確定樹結構,即每次特徵分裂怎麼尋找最佳特徵,怎麼尋找最佳分裂點。

XGBoost使用了和CART迴歸樹一樣的想法,利用貪心算法,遍歷所有特徵的所有特徵劃分點。具體做法就是分裂後的目標函數值比單子葉子節點的目標函數的增益,同時爲了限制樹生長過深,還加了個閾值,只有當增益大於該閾值才進行分裂。

假設ILI_LIRI_R是拆分後的左右節點的實例集,且滿足I=ILIRI=I_L\bigcup I_R,拆分之後損失減少爲:

Lsplit=12[(iILgi)2iILhi+λ+(iIRgi)2iIRhi+λ(iIgi)2iIhi+λ]rL_{split}=\frac12\left[ \frac{(\sum_{i\in I_L}g_i)^2}{\sum_{i\in I_L}h_i+\lambda}+\frac{(\sum_{i\in I_R}g_i)^2}{\sum_{i\in I_R}h_i+\lambda}-\frac{(\sum_{i\in I}g_i)^2}{\sum_{i\in I}h_i+\lambda} \right]-r

這個公式通常被用於評估分割候選集(選擇最優分割點),其中前兩項分別是切分後左右子樹的的分支之和,第三項是未切分前該父節點的分數值,最後一項是引入額外的葉節點導致的複雜度。同時可以設置樹的最大深度、當樣本權重和小於設定閾值時停止生長去防止過擬合。

正則化

XGBoost的正則化項爲:
Ω(f)=rT+12λj=1Twj2\Omega (f)=r T+\frac12\lambda \sum_{j=1}^Tw_j^2
這裏的r和λ\lambda,這是XGBoost自己定義的,在使用XGBoost時,你可以設定它們的值,顯然,r越大,表示越希望獲得結構簡單的樹,因爲此時對較多葉子節點的樹的懲罰越大。λ\lambda越大也是越希望獲得結構簡單的樹。

總結

作爲GBDT的高效實現,XGBoost是一個上限特別高的算法,因此在算法競賽中比較受歡迎。簡單來說,對比原算法GBDT,XGBoost主要從下面三個方面做了優化:

一是算法本身的優化:在算法的弱學習器模型選擇上,對比GBDT只支持決策樹,還可以直接很多其他的弱學習器。在算法的損失函數上,除了本身的損失,還加上了正則化部分。在算法的優化方式上,GBDT的損失函數只對誤差部分做負梯度(一階泰勒)展開,而XGBoost損失函數對誤差部分做二階泰勒展開,更加準確。

二是算法運行效率的優化:對每個弱學習器,比如決策樹建立的過程做並行選擇,找到合適的子樹分裂特徵和特徵值。在並行選擇之前,先對所有的特徵的值進行排序分組,方便前面說的並行選擇。對分組的特徵,選擇合適的分組大小,使用CPU緩存進行讀取加速。將各個分組保存到多個硬盤以提高IO速度。

三是算法健壯性的優化:對於缺失值的特徵,通過枚舉所有缺失值在當前節點是進入左子樹還是右子樹來決定缺失值的處理方式。算法本身加入了L1和L2正則化項,可以防止過擬合,泛化能力更強。

lightGBM

對所有特徵都按照特徵的數值進行預排序。其次,在遍歷分割點的時候用O(#data)的代價找到一個特徵上的最好分割點。最後,在找到一個特徵的最好分割點後,將數據分裂成左右子節點。

這樣的預排序算法的優點是能精確地找到分割點。但是缺點也很明顯:首先,空間消耗大。這樣的算法需要保存數據的特徵值,還保存了特徵排序的結果(例如,爲了後續快速的計算分割點,保存了排序後的索引),這就需要消耗訓練數據兩倍的內存。其次,時間上也有較大的開銷,在遍歷每一個分割點的時候,都需要進行分裂增益的計算,消耗的代價大。

最後,對cache優化不友好。在預排序後,特徵對梯度的訪問是一種隨機訪問,並且不同的特徵訪問的順序不一樣,無法對cache進行優化。同時,在每一層長樹的時候,需要隨機訪問一個行索引到葉子索引的數組,並且不同特徵訪問的順序也不一樣,也會造成較大的cache miss。

  • 基於Histogram的決策樹算法。
  • 單邊梯度採樣 Gradient-based One-Side Sampling(GOSS):使用GOSS可以減少大量只具有小梯度的數據實例,這樣在計算信息增益的時候只利用剩下的具有高梯度的數據就可以了,相比XGBoost遍歷所有特徵值節省了不少時間和空間上的開銷。
  • 互斥特徵捆綁 Exclusive Feature Bundling(EFB):使用EFB可以將許多互斥的特徵綁定爲一個特徵,這樣達到了降維的目的。
  • 帶深度限制的Leaf-wise的葉子生長策略:大多數GBDT工具使用低效的按層生長 (level-wise) 的決策樹生長策略,因爲它不加區分的對待同一層的葉子,帶來了很多沒必要的開銷。實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。LightGBM使用了帶有深度限制的按葉子生長 (leaf-wise) 算法。
  • 直接支持類別特徵(Categorical Feature)
  • 支持高效並行
Histogram的決策樹算法

Histogram algorithm應該翻譯爲直方圖算法,直方圖算法的基本思想是:先把連續的浮點特徵值離散化成k個整數,同時構造一個寬度爲k的直方圖。在遍歷數據的時候,根據離散化後的值作爲索引在直方圖中累積統計量,當遍歷一次數據後,直方圖累積了需要的統計量,然後根據直方圖的離散值,遍歷尋找最優的分割點。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-kmh6Agad-1592467489718)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p70)]
直方圖算法簡單理解爲:首先確定對於每一個特徵需要多少個箱子(bin)併爲每一個箱子分配一個整數;然後將浮點數的範圍均分成若干區間,區間個數與箱子個數相等,將屬於該箱子的樣本數據更新爲箱子的值;最後用直方圖(#bins)表示。看起來很高大上,其實就是直方圖統計,將大規模的數據放在了直方圖中。

我們知道特徵離散化具有很多優點,如存儲方便、運算更快、魯棒性強、模型更加穩定等。對於直方圖算法來說最直接的有以下兩個優點:

  • 內存佔用更小: 直方圖算法不僅不需要額外存儲預排序的結果,而且可以只保存特徵離散化後的值,而這個值一般用8位整型存儲就足夠了,內存消耗可以降低爲原來的1/8。也就是說XGBoost需要用32位的浮點數去存儲特徵值,並用32位的整形去存儲索引,而 LightGBM只需要用8位去存儲直方圖,內存相當於減少爲1/8;
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qyL9eU7D-1592467489722)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p71)]

  • 計算代價更小: 預排序算法XGBoost每遍歷一個特徵值就需要計算一次分裂的增益,而直方圖算法LightGBM只需要計算k次( k可以認爲是常數),直接將時間複雜度從O(#data*#feature)降低到 O(k*#feature) ,而我們知道#data>>k。

LightGBM另一個優化是Histogram(直方圖)做差加速。一個葉子的直方圖可以由它的父親節點的直方圖與它兄弟的直方圖做差得到,在速度上可以提升一倍。通常構造直方圖時,需要遍歷該葉子上的所有數據,但直方圖做差僅需遍歷直方圖的k個桶。在實際構建樹的過程中,LightGBM還可以先計算直方圖小的葉子節點,然後利用直方圖做差來獲得直方圖大的葉子節點,這樣就可以用非常微小的代價得到它兄弟葉子的直方圖。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wTTTUjzH-1592467489739)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p72)]

注意: XGBoost 在進行預排序時只考慮非零值進行加速,而 LightGBM 也採用類似策略:只用非零特徵構建直方圖。

帶深度限制的 Leaf-wise 算法

在Histogram算法之上,LightGBM進行進一步的優化。首先它拋棄了大多數GBDT工具使用的按層生長 (level-wise) 的決策樹生長策略,而使用了帶有深度限制的按葉子生長 (leaf-wise) 算法。

XGBoost 採用 Level-wise 的增長策略,該策略遍歷一次數據可以同時分裂同一層的葉子,容易進行多線程優化,也好控制模型複雜度,不容易過擬合。但實際上Level-wise是一種低效的算法,因爲它不加區分的對待同一層的葉子,實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂,因此帶來了很多沒必要的計算開銷。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HERk2UuQ-1592467489742)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p73)]
LightGBM採用Leaf-wise的增長策略,該策略每次從當前所有葉子中,找到分裂增益最大的一個葉子,然後分裂,如此循環。因此同Level-wise相比,Leaf-wise的優點是:在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度;Leaf-wise的缺點是:可能會長出比較深的決策樹,產生過擬合。因此LightGBM會在Leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uToq3h31-1592467489744)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p74)]

單邊梯度採樣算法

Gradient-based One-Side Sampling 應該被翻譯爲單邊梯度採樣(GOSS)。GOSS算法從減少樣本的角度出發,排除大部分小梯度的樣本,僅用剩下的樣本計算信息增益,它是一種在減少數據量和保證精度上平衡的算法。

AdaBoost中,樣本權重是數據重要性的指標。然而在GBDT中沒有原始樣本權重,不能應用權重採樣。幸運的是,我們觀察到GBDT中每個數據都有不同的梯度值,對採樣十分有用。即梯度小的樣本,訓練誤差也比較小,說明數據已經被模型學習得很好了,直接想法就是丟掉這部分梯度小的數據。然而這樣做會改變數據的分佈,將會影響訓練模型的精確度,爲了避免此問題,提出了GOSS算法。

GOSS是一個樣本的採樣算法,目的是丟棄一些對計算信息增益沒有幫助的樣本留下有幫助的。根據計算信息增益的定義,梯度大的樣本對信息增益有更大的影響。因此,GOSS在進行數據採樣的時候只保留了梯度較大的數據,但是如果直接將所有梯度較小的數據都丟棄掉勢必會影響數據的總體分佈。所以,GOSS首先將要進行分裂的特徵的所有取值按照絕對值大小降序排序(XGBoost一樣也進行了排序,但是LightGBM不用保存排序後的結果),選取絕對值最大的α\alpha * 100100%個數據。然後在剩下的1α1-\alpha * 100100%個數據較小梯度數據中隨機選擇bb * 100100%個數據。接着將這bb * 100100%個數據乘以一個常數1ab\frac{1-a}b 【計算信息增益時將其放大】,這樣算法就會更關注訓練不足的樣本,而不會過多改變原數據集的分佈。最後使用這aa% * #samples + b% * (1 - a%) * #samples個數據來計算信息增益。下圖是GOSS的具體算法。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-F4lRKa9J-1592467489752)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p75)]

互斥特徵捆綁算法

高維度的數據往往是稀疏的,這種稀疏性啓發我們設計一種無損的方法來減少特徵的維度。通常被捆綁的特徵都是互斥的(即特徵不會同時爲非零值,像one-hot),這樣兩個特徵捆綁起來纔不會丟失信息。如果兩個特徵並不是完全互斥(部分情況下兩個特徵都是非零值),可以用一個指標對特徵不互斥程度進行衡量,稱之爲衝突比率,當這個值較小時,我們可以選擇把不完全互斥的兩個特徵捆綁,而不影響最後的精度。互斥特徵捆綁算法(Exclusive Feature Bundling, EFB)指出如果將一些特徵進行融合綁定,則可以降低特徵數量。

  • 哪些特徵應該綁在一起
    將相互獨立的特徵進行綁定是一個 NP-Hard 問題,LightGBM的EFB算法將這個問題轉化爲圖着色的問題來求解,將所有的特徵視爲圖的各個頂點,將不是相互獨立的特徵用一條邊連接起來,邊的權重就是兩個相連接的特徵的總衝突值,這樣需要綁定的特徵就是在圖着色問題中要塗上同一種顏色的那些點(特徵)。此外,我們注意到通常有很多特徵,儘管不是
    100%相互排斥,但也很少同時取非零值。如果我們的算法可以允許一小部分的衝突,我們可以得到更少的特徵包,進一步提高計算效率。經過簡單的計算,隨機污染小部分特徵值將影響精度最多O([(1r)n]23)O([(1-r)n]^{-\frac23})rr 是每個綁定中的最大沖突比率,當其相對較小時,能夠完成精度和效率之間的平衡。具體步驟可以總結如下:

    • 構造一個加權無向圖,頂點是特徵,邊有權重,其權重與兩個特徵間衝突相關;
    • 根據節點的度進行降序排序,度越大,與其它特徵的衝突越大;
    • 遍歷每個特徵,將它分配給現有特徵包,或者新建一個特徵包,使得總體衝突最小。

    算法允許兩兩特徵並不完全互斥來增加特徵捆綁的數量,通過設置最大沖突比率rr來平衡算法的精度和效率。EFB 算法的僞代碼如下所示:
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gTBOlLzv-1592467489754)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENNote/p43?hash=036a5a53ec7fdc75546023a743638735)]
    算法3的時間複雜度是O(feature2)O(feature^2),訓練之前只處理一次,其時間複雜度在特徵不是特別多的情況下是可以接受的,但難以應對百萬維度的特徵。爲了繼續提高效率,LightGBM提出了一種更加高效的無圖的排序策略:將特徵按照非零值個數排序,這和使用圖節點的度排序相似,因爲更多的非零值通常會導致衝突,新算法在算法3基礎上改變了排序策略

  • 解決怎麼把特徵綁爲一捆
    特徵合併算法,其關鍵在於原始特徵能從合併的特徵中分離出來。綁定幾個特徵在同一個bundle裏需要保證綁定前的原始特徵的值可以在bundle中識別,考慮到histogram-based算法將連續的值保存爲離散的bins,我們可以使得不同特徵的值分到bundle中的不同bin(箱子)中,這可以通過在特徵值中加一個偏置常量來解決。比如,我們在bundle中綁定了兩個特徵A和B,A特徵的原始取值爲區間[0,10],B特徵的原始取值爲區間[0,20,我們可以在B特徵的取值上加一個偏置常量10,將其取值範圍變爲[10,30],綁定後的特徵取值範圍爲[0,30] ,這樣就可以放心的融合特徵A和B了。具體的特徵合併算法如下所示:
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JoHe1M6C-1592467489755)(evernotecid://DD492144-9AFF-43C1-9BC0-5A625709FC62/appyinxiangcom/28357599/ENResource/p78)]

LightGBM 相對於 XGBoost 的優點
  1. 速度更快
  • LightGBM 採用了直方圖算法將遍歷樣本轉變爲遍歷直方圖,極大的降低了時間複雜度;
  • LightGBM 在訓練過程中採用單邊梯度算法過濾掉梯度小的樣本,減少了大量的計算;
  • LightGBM 採用了基於 Leaf-wise 算法的增長策略構建樹,減少了很多不必要的計算量;
  • LightGBM 採用優化後的特徵並行、數據並行方法加速計算,當數據量非常大的時候還可以採用投票並行的策略;
  • LightGBM 對緩存也進行了優化,增加了緩存命中率;
  1. 內存更小
  • XGBoost使用預排序後需要記錄特徵值及其對應樣本的統計值的索引,而 LightGBM 使用了直方圖算法將特徵值轉變爲 bin 值,且不需要記錄特徵到樣本的索引,將空間複雜度從 降低爲 ,極大的減少了內存消耗;
  • LightGBM 採用了直方圖算法將存儲特徵值轉變爲存儲 bin 值,降低了內存消耗;
  • LightGBM 在訓練過程中採用互斥特徵捆綁算法減少了特徵數量,降低了內存消耗。

代碼測試

爲了測試時間我們需要使用一個比較大的數據集,所以選取了大家熟悉的MNIST數據集

先上XGboost

tt = time.time()
#dmatrix 格式 在xgboost當中運行速度更快,性能更好。
dtrain = xgb.DMatrix(x_train, label=y_train)
dtest = xgb.DMatrix(x_valid, label=y_valid)

xgb_params = {
    'seed': 0,
    'eta': 0.1,
    'colsample_bytree': 0.5,
    'silent': 1,
    'subsample': 0.5,
    'objective': 'multi:softmax',
    'num_class':10,
    'max_depth': 4,
    'min_child_weight': 3
}


bst = xgb.train(xgb_params, dtrain, 100, evals=[(dtrain,'train'), (dtest,'test')])

preds = bst.predict(dtest)
auc = accuracy_score(y_valid, preds)

print(auc)
print('Time used: {} sec'.format(time.time()-tt))

0.959
Time used: 1098.1514909267426 sec

再看看lightgbm

tt = time.time()
# 轉換爲Dataset數據格式
train_data = lgb.Dataset(x_train, label=y_train)
validation_data = lgb.Dataset(x_valid, label=y_valid)

# 參數
params = {
    'learning_rate': 0.1,
    'lambda_l1': 0.1,
    'lambda_l2': 0.2,
    'max_depth': 4,
    'objective': 'multiclass',  # 目標函數
    'num_class': 10,
}
# 模型訓練
gbm = lgb.train(params, train_data, valid_sets=[validation_data])

# 模型預測
y_pred = gbm.predict(x_valid)
#print(y_pred)
y_pred = [list(x).index(max(x)) for x in y_pred]
print(y_pred)

# 模型評估
print(accuracy_score(y_valid, y_pred))
print('Time used: {} sec'.format(time.time()-tt))

0.9568
Time used: 74.20362401008606 sec

我們可以看到兩者的準確率相差不大,但是時間上lightGBM快了很多
這裏要提高準確率,可以自己調參進行測試,當然最好找一個比較小的數據集

後續:DeepGBM

參考:
https://mp.weixin.qq.com/s/zejkifZnYXAfgTRrkMaEww
https://blog.csdn.net/Andy_shenzl/article/details/105631577

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章