一、LightGBM簡介:
- 所屬:boosting迭代型、樹類算法
- 適用范圍:回歸/分類/排序
- LightGBM工具包:lightGBM英文文檔 | lightGBM中文文檔
- 論文鏈接
- 優點:
- 基於Histogram的決策樹算法
- 帶深度限制的Leaf-wise的葉子生長策略
- 直方圖做差加速
- 直接支持類別特征(Categorical Feature)
- Cache命中率優化
- 基於直方圖的稀疏特征優化
- 多線程優化
LightGBM提出的主要原因是為了解決GBDT在海量數據遇到的問題,讓GBDT可以更好更快地用於工業實踐。
二、XGboost缺點
XGboost的不足之處主要有:
1.精確貪心算法
每輪迭代時,都需要遍歷整個訓練數據多次。如果把整個訓練數據裝進內存則會限制訓練數據的大小;如果不裝進內存,反復地讀寫訓練數據又會消耗非常大的時間。
優點:可以找到精確的划分條件
缺點:
- 計算量巨大;
- 內存占用巨大;
- 易產生過擬合
2.預排序方法(pre-sorted)
首先,空間消耗大。這樣的算法需要保存數據的特征值,還保存了特征排序的結果(例如排序后的索引,為了后續快速的計算分割點),這里需要消耗訓練數據兩倍的內存。其次時間上也有較大的開銷,在遍歷每一個分割點的時候,都需要進行分裂增益的計算,消耗的代價大。
優點:
- 可以使用多線程
- 可以加速精確貪心算法
缺點:效率低下,可能產生不必要的葉結點
3.level-wise
生成決策樹是level-wise級別的,也就是預先設置好樹的深度之后,每一顆樹都需要生長到設置的那個深度,這樣有些樹在某一次分裂之后效果甚至沒有提升但仍然會繼續划分樹枝,然后再次划分....之后就是無用功了,耗時。
4.對cache優化不友好
在預排序后,特征對梯度的訪問是一種隨機訪問,並且不同的特征訪問的順序不一樣,無法對cache進行優化。同時,在每一層長樹的時候,需要隨機訪問一個行索引到葉子索引的數組,並且不同特征訪問的順序也不一樣,也會造成較大的cache miss。
三、LightGBM對Xgboost的優化
1.基於Histogram的決策樹算法
思想:將連續的浮點特征離散成k個離散值,具體過程是首先確定對於每一個特征需要多少的桶bin,然后均分,將屬於該桶的樣本數據更新為bin的值,最后用直方圖表示。在進行特征選擇時,只需要根據直方圖的離散值,遍歷尋找最優的分割點。
使用直方圖算法有很多優點。首先最明顯就是內存消耗的降低,直方圖算法不僅不需要額外存儲預排序的結果,而且可以只保存特征離散化后的值,而這個值一般用8位整型存儲就足夠了,內存消耗可以降低為原來的1/8。
然后在計算上的代價也大幅降低,預排序算法每遍歷一個特征值就需要計算一次分裂的增益,而直方圖算法只需要計算k次(k可以認為是常數),時間復雜度從O(#data*#feature)優化到O(k*#features)。
Histogram算法有幾個需要注意的地方:
- 使用bin替代原始數據相當於增加了正則化;
- 使用bin意味着很多數據的細節特征被放棄了,相似的數據可能被划分到相同的桶中,這樣的數據之間的差異就消失了;
- bin數量選擇決定了正則化的程度,bin越少懲罰越嚴重,欠擬合風險越高。
- 構建直方圖時不需要對數據進行排序(比XGBoost快),因為預先設定了bin的范圍;
- 直方圖除了保存划分閾值和當前bin內樣本數以外還保存了當前bin內所有樣本的一階梯度和(一階梯度和的平方的均值等價於均方損失);
- 閾值的選取是按照直方圖從小到大遍歷,使用了上面的一階梯度和,目的是得到划分之后△loss最大的特征及閾值。
Histogram算法的優缺點:
- Histogram算法並不是完美的。由於特征被離散化后,找到的並不是很精確的分割點,所以會對結果產生影響。但在實際的數據集上表明,離散化的分裂點對最終的精度影響並不大,甚至會好一些。原因在於decision tree本身就是一個弱學習器,采用Histogram算法會起到正則化的效果,有效地防止模型的過擬合。
- 時間上的開銷由原來的O(#data * #features)降到O(k * #features)。由於離散化,#bin遠小於#data,因此時間上有很大的提升。
Histogram算法還可以進一步加速:
- 一個葉子節點的Histogram可以直接由父節點的Histogram和兄弟節點的Histogram做差得到。一般情況下,構造Histogram需要遍歷該葉子上的所有數據,通過該方法,只需要遍歷Histogram的k個捅。速度提升了一倍。
2.帶深度限制的Leaf-wise的葉子生長策略
在Histogram算法之上,LightGBM進行進一步的優化。首先它拋棄了大多數GBDT工具使用的按層生長 (level-wise)的決策樹生長策略,而使用了帶有深度限制的按葉子生長 (leaf-wise)算法。
XGBoost采用的是按層生長level(depth)-wise生長策略,能夠同時分裂同一層的葉子,從而進行多線程優化,不容易過擬合;但不加區分的對待同一層的葉子,帶來了很多沒必要的開銷。因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。
LightGBM采用leaf-wise生長策略,每次從當前所有葉子中找到分裂增益最大(一般也是數據量最大)的一個葉子,然后分裂,如此循環。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。Leaf-wise的缺點是可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合。
3.直方圖做差加速
一個葉子的直方圖可以由它的父親節點的直方圖與它兄弟的直方圖做差得到。通常構造直方圖,需要遍歷該葉子上的所有數據,但直方圖做差僅需遍歷直方圖的k個桶。利用這個方法,LightGBM可以在構造一個葉子的直方圖后,可以用非常微小的代價得到它兄弟葉子的直方圖,在速度上可以提升一倍。
4.直接支持類別特征
實際上大多數機器學習工具都無法直接支持類別特征,一般需要把類別特征,轉化one-hot特征,降低了空間和時間的效率。而類別特征的使用是在實踐中很常用的。基於這個考慮,LightGBM優化了對類別特征的支持,可以直接輸入類別特征,不需要額外的0/1展開。並在決策樹算法上增加了類別特征的決策規則。
one-hot編碼是處理類別特征的一個通用方法,然而在樹模型中,這可能並不一定是一個好的方法,尤其當類別特征中類別個數很多的情況下。主要的問題是:
- 可能無法在這個類別特征上進行切分(即浪費了這個特征)。使用one-hot編碼的話,意味着在每一個決策節點上只能使用one vs rest(例如是不是狗,是不是貓等)的切分方式。當類別值很多時,每個類別上的數據可能會比較少,這時候切分會產生不平衡,這意味着切分增益也會很小(比較直觀的理解是,不平衡的切分和不切分沒有區別)。
- 會影響決策樹的學習。因為就算可以在這個類別特征進行切分,也會把數據切分到很多零碎的小空間上,如圖1左邊所示。而決策樹學習時利用的是統計信息,在這些數據量小的空間上,統計信息不准確,學習會變差。但如果使用下圖右邊的分裂方式,數據會被切分到兩個比較大的空間,進一步的學習也會更好。
下圖右邊葉子節點的含義是X=A或者X=C放到左孩子,其余放到右孩子。
具體實現方法:
為了解決one-hot編碼處理類別特征的不足。LightGBM采用了Many vs many的切分方式,實現了類別特征的最優切分。用LightGBM可以直接輸入類別特征,並產生上圖右邊的效果。在1個k維的類別特征中尋找最優切分,朴素的枚舉算法的復雜度是$O(2^k)$,而LightGBM采用了如On Grouping For Maximum Homogeneity的方法實現了$O(klogk)$的算法。
算法流程下圖所示:在枚舉分割點之前,先把直方圖按每個類別的均值進行排序;然后按照均值的結果依次枚舉最優分割點。從下圖可以看到,Sum(y)/Count(y)為類別的均值。當然,這個方法很容易過擬合,所以在LGBM中加入了很多對這個方法的約束和正則化。
- 離散特征建立直方圖的過程:統計該特征下每一種離散值出現的次數,並從高到低排序,並過濾掉出現次數較少的特征值, 然后為每一個特征值,建立一個bin容器, 對於在bin容器內出現次數較少的特征值直接過濾掉,不建立bin容器。
- 計算分裂閾值的過程:
- 先看該特征下划分出的bin容器的個數,如果bin容器的數量小於4,直接使用one vs other方式, 逐個掃描每一個bin容器,找出最佳分裂點;
- 對於bin容器較多的情況, 先進行過濾,只讓子集合較大的bin容器參加划分閾值計算, 對每一個符合條件的bin容器進行公式計算(公式如下: 該bin容器下所有樣本的一階梯度之和/該bin容器下所有樣本的二階梯度之和 + 正則項(參數cat_smooth),這里為什么不是label的均值呢?其實上例中只是為了便於理解,只針對了學習一棵樹且是回歸問題的情況, 這時候一階導數是Y, 二階導數是1),得到一個值,根據該值對bin容器從小到大進行排序,然后分從左到右、從右到左進行搜索,得到最優分裂閾值。但是有一點,沒有搜索所有的bin容器,而是設定了一個搜索bin容器數量的上限值,程序中設定是32,即參數max_num_cat。LightGBM中對離散特征實行的是many vs many 策略,這32個bin中最優划分的閾值的左邊或者右邊所有的bin容器就是一個many集合,而其他的bin容器就是另一個many集合。
- 對於連續特征,划分閾值只有一個,對於離散值可能會有多個划分閾值,每一個划分閾值對應着一個bin容器編號,當使用離散特征進行分裂時,只要數據樣本對應的bin容器編號在這些閾值對應的bin集合之中,這條數據就加入分裂后的左子樹,否則加入分裂后的右子樹。
5.Cache命中率優化
6.基於直方圖的稀疏特征優化
7.多線程優化
LightGBM原生支持並行學習,目前支持特征並行和數據並行的兩種。特征並行的主要思想是在不同機器在不同的特征集合上分別尋找最優的分割點,然后在機器間同步最優的分割點。數據並行則是讓不同的機器先在本地構造直方圖,然后進行全局的合並,最后在合並的直方圖上面尋找最優分割點。
LightGBM針對這兩種並行方法都做了優化,在特征並行算法中,通過在本地保存全部數據避免對數據切分結果的通信;在數據並行中使用分散規約(Reduce scatter)把直方圖合並的任務分攤到不同的機器,降低通信和計算,並利用直方圖做差,進一步減少了一半的通信量。
基於投票的數據並行則進一步優化數據並行中的通信代價,使通信代價變成常數級別。在數據量很大的時候,使用投票並行可以得到非常好的加速效果。
四、LightGBM原理
為了能夠在不損害准確率的條件下加快GBDT模型的訓練速度,lightGBM在傳統的GBDT算法上加了兩個技術:
- 單邊梯度采樣 Gradient-based One-Side Sampling (GOSS):排除大部分小梯度的樣本,僅用剩下的樣本計算信息增益。
- 互斥稀疏特征綁定Exclusive Feature Bundling (EFB):從減少特征角度
GBDT雖然沒有數據權重,但每個數據實例有不同的梯度,根據計算信息增益的定義,梯度大的實例對信息增益有更大的影響,因此在下采樣時,我們應該盡量保留梯度大的樣本(預先設定閾值,或者最高百分位間),隨機去掉梯度小的樣本。我們證明此措施在相同的采樣率下比隨機采樣獲得更准確的結果,尤其是在信息增益范圍較大時。
捆綁互斥特征,也就是他們很少同時取非零值(也就是用一個合成特征代替)。通常應用中,雖然特征量比較多,但是由於特征空間十分稀疏,是否可以設計一種無損的方法來減少有效特征呢?特別在稀疏特征空間上,許多特征幾乎是互斥的(例如許多特征不會同時為非零值,像one-hot),我們可以捆綁互斥的特征。最后,我們將捆綁問題歸約到圖着色問題,通過貪心算法求得近似解。
1. Gradient-based One-Side Sampling(GOSS)
GOSS在進行數據采樣的時候只保留了梯度較大的數據,但是如果直接將所有梯度較小的數據都丟棄掉勢必會影響數據的總體分布.為了抵消對數據分布的影響,計算信息增益的時候,GOSS對小梯度的數據引入常量乘數。GOSS首先根據數據的梯度絕對值排序,選取top a個實例。然后在剩余的數據中隨機采樣b個實例。接着計算信息增益時為采樣出的小梯度數據乘以(1-a)/b,這樣算法就會更關注訓練不足的實例,而不會過多改變原數據集的分布。
- 首先根據數據的梯度將訓練降序排序。
- 保留top a個數據實例,作為數據子集A。
- 對於剩下的數據的實例,隨機采樣獲得大小為b的數據子集B。
- 最后我們通過以下方程估計信息增益:
2. Exclusive Feature Bundling(EFB)
EFB是通過特征捆綁的方式減少特征維度(其實是降維技術)的方式,來提升計算效率。通常被捆綁的特征都是互斥的(一個特征值為零,一個特征值不為零),這樣兩個特征捆綁起來才不會丟失信息。如果兩個特征並不是完全互斥(部分情況下兩個特征都是非零值),可以用一個指標對特征不互斥程度進行衡量,稱之為沖突比率,當這個值較小時,我們可以選擇把不完全互斥的兩個特征捆綁,而不影響最后的精度。
EBF的算法步驟如下:
- 將特征按照非零值的個數進行排序
- 計算不同特征之間的沖突比率
- 遍歷每個特征並嘗試合並特征,使沖突比率最小化
高位的數據通常是稀疏的,這種稀疏性啟發我們設計一種無損地方法來減少特征的維度。特別的,稀疏特征空間中,許多特征是互斥的,例如他們從不同時為非零值。我們可以綁定互斥的特征為單一特征,通過仔細設計特征臊面算法,我們從特征捆綁中構建了與單個特征相同的特征直方圖。這種方式的間直方圖時間復雜度從O(#data * #feature)降到O(#data * #bundle),由於#bundle << # feature,我們能夠極大地加速GBDT的訓練過程而且損失精度。
有兩個問題:
- 怎么判定那些特征應該綁在一起(build bundled)?
- 怎么把特征綁為一個(merge feature)?
理論1:將特征分割為較小量的互斥特征群是NP難的
bundle(什么樣的特征被綁定)算法流程:
- 建立一個圖,每個點代表特征,每個邊有權重,其權重和特征之間總體沖突相關。
- 按照降序排列圖中的度數來排序特征。
- 檢查排序之后的每個特征,對他進行特征綁定或者建立新的綁定使得操作之后的總體沖突最小。
merging features(特征合並):
如何合並同一個bundle的特征來降低訓練時間復雜度。關鍵在於原始特征值可以從bundle中區分出來。鑒於直方圖算法存儲離散值而不是連續特征值,我們通過將互斥特征放在不同的箱中來構建bundle。這可以通過將偏移量添加到特征原始值中實現,例如,假設bundle中有兩個特征,原始特征A取值[0, 10],B取值[0, 20]。我們添加偏移量10到B中,因此B取值[10, 30]。通過這種做法,就可以安全地將A、B特征合並,使用一個取值[0, 30]的特征取代AB。
EFB算法能夠將許多互斥的特征變為低維稠密的特征,就能夠有效的避免不必要0值特征的計算。實際,通過用表記錄數據中的非零值,來忽略零值特征,達到優化基礎的直方圖算法。通過掃描表中的數據,建直方圖的時間復雜度將從O(#data)降到O(#non_zero_data)。當然,這種方法在構建樹過程中需要而額外的內存和計算開銷來維持預特征表。我們在lightGBM中將此優化作為基本函數,因為當bundles是稀疏的時候,這個優化與EFB不沖突(可以用於EFB)
五、LightGBM參數調優
下面幾張表為重要參數的含義和如何應用
接下來是調參
下表對應了Faster Spread,better accuracy,over-fitting三種目的時,可以調整的參數
參考文獻:
【3】LightGBM——提升機器算法(圖解+理論+安裝方法+python代碼)
【4】https://www.bilibili.com/video/av47496956?from=search&seid=11905257687121452350