[机器学习] Boosting算法4 --- LightGBM介绍与分布式
[機器學習] Boosting算法1 --- AdaBoost
[機器學習] Boosting算法2 --- GBDT
[機器學習] Boosting算法3 --- XGBoost
[機器學習] Boosting算法4 --- LightGBM
目錄
一 LightGBM特點
二 Histogram算法
三 LightGBM的細節技術
1. Histogram optimization
2 內存消耗和計算上優化
3 帶深度限制的Leaf-wise的葉子生長策略
4、直方圖做差優化
5、 增加緩存命中率
6、支持類別特征
7、支持并行學習
7.1 特征并行
7.2 數據并行
7.3 投票并行
8、網絡通信的優化
四、支持的應用和度量
1 應用
2 度量
3 其他
一? LightGBM特點
LightGBM(Light Gradient Boosting Machine)是微軟的開源分布式高性能Gradient Boosting框架,使用基于決策樹的學習算法。
相比XGBoost有如下優點:
-
基于Histogram的決策樹算法, 更快的訓練速度和更高的效率:LightGBM使用基于直方圖的算法。例如,它將連續的特征值分桶(buckets)裝進離散的箱子(bins),這是的訓練過程中變得更快。
-
帶深度限制的Leaf-wise的葉子生長策略,?? LightGBM的分裂節點的方式與XGBoost不一樣。LGB避免了對整層節點分裂法,而采用了對增益最大的節點進行深入分解的方法。這樣節省了大量分裂節點的資源。
-
更低的內存占用:使用離散的箱子(bins)保存并替換連續值導致更少的內存占用。
-
更高的準確率(相比于其他任何提升算法):它通過leaf-wise分裂方法產生比level-wise分裂方法更復雜的樹,這就是實現更高準確率的主要因素。然而,它有時候或導致過擬合,但是我們可以通過設置 max-depth 參數來防止過擬合的發生。
-
大數據處理能力:相比于XGBoost,由于它在訓練時間上的縮減,它同樣能夠具有處理大數據的能力。
-
支持并行學習
-
Cache命中率優化
-
基于直方圖的稀疏特征優化
二 Histogram算法
直方圖算法的基本思想:先把連續的浮點特征值離散化成k個整數,同時構造一個寬度為k的直方圖。遍歷數據時,根據離散化后的值作為索引在直方圖中累積統計量,當遍歷一次數據后,直方圖累積了需要的統計量,然后根據直方圖的離散值,遍歷尋找最優的分割點。
LightGBM里默認的訓練決策樹時使用直方圖算法,XGBoost里現在也提供了這一選項,不過默認的方法是對特征預排序,計算過程當中是按照value的排序,逐個數據樣本來計算劃分收益,這樣的算法能夠精確的找到最佳劃分值,但是代價比較大同時也沒有較好的推廣性。
a. 降低計算分裂增益的成本
b. 直方圖做差進一步提高效率
計算某一節點的葉節點的直方圖可以通過將該節點的直方圖與另一子節點的直方圖做差得到,所以每次分裂只需計算分裂后樣本數較少的子節點的直方圖然后通過做差的方式獲得另一個子節點的直方圖,進一步提高效率。
c. 節省內存
- 將連續數據離散化為直方圖的形式,對于數據量較小的情形可以使用小型的數據類型來保存訓練數據
- 不必像預排序一樣保留額外的對特征值進行預排序的信息
d. 減少了并行訓練的通信代價
現在來看看直方圖優化是如何優化的,當然這個優化也是在處理節點分裂的時候。在處理連續特征的時候,如果你想要快速找到最佳的分裂節點要么像之前說到的那樣對特征值采用預排序的方式來快速得到最佳的分裂特征值,在這里直方圖就是先將特征值先做裝箱處理,裝箱處理是特征工程中常見的處理方式之一
以浮點型數據來舉例,一個區間的值會被作為一個筒,然后以這些筒為精度單位的直方圖來做。這樣一來,數據的表達變得更加簡化,減少了內存的使用,而且直方圖帶來了一定的正則化的效果,能夠使我們做出來的模型避免過擬合且具有更好的推廣性。
histogram算法簡單來說,就是先對特征值進行裝箱處理,形成一個一個的bins。對于連續特征來說,裝箱處理就是特征工程中的離散化:如[0,0.3)—>0,[0.3,0.7)—->1等。
一個區間的范圍內作為一個bin,簡化為以分桶為粒度的直方圖來做,這樣一來,數據的表示更加簡化,減少了內存的適用,而且直方圖帶來了一定的正則化的效果,使得我們訓練出的模型不容易over-fitting到training-data上面,從而具備更好的推廣性。
?
e. 特征的最優分割點
通常使用獨熱編碼來轉換分類特征,但這種方法對于決策樹的學習并不是有益的。特別是對于不同值較多的特征,獨熱編碼后構建的樹往往是不平衡的,并且需要非常大的深度才能獲得較好的準確率。
事實上,最佳解決方案是通過將類別劃分為2個子集。如果特征具有K個不同的值,就是在2^(k-1) - 1種情況里找到最優的分割點。對于回歸樹而言,有一種解決方案可以保證在O(k * log(k))的時間復雜度內找到最優分割點。
找到特征的最優分割點的基本思想是根據訓練目標的相關性對類別進行重排序。 更具體的說,根據累加值(sum_gradient / sum_hessian)重新對(類別特征的)直方圖進行排序,然后在排好序的直方圖中尋找最優的分割點。
三、LightGBM的細節技術
1. Histogram optimization
上圖是做過直方圖優化之后的求解直方圖的算法細節。這是按照bin來索引histogram的,所以不需要按照每個feature來排序,也不需要一一地對比不同feature的值,大大地減少了運算量。
在Lightgbm中默認的#bins為256(1個字節的能表示的長度,可以設置)。對于分類特征來說,則是每一種取值放入一個bin,且當取值的個數大于max bin數時,會忽略那些很少出現的category值。在節點分裂的時候,這時候就不需要按照預排序算法那樣,對于每個特征都計算#data遍了,而是只需要計算#bins遍,這樣就大大加快了訓練速度。
2 內存消耗和計算上優化
相比于另一個主流的算法 pre-sorted(如 xgboost 中的 exact 算法)histogram 在內存消耗和計算代價上都有不少優勢。
a. 內存上優勢
1. 當我們用feature的bin來描述數據的特征的時候,帶來的變化,首先是我們不需要像預排序算法那樣去存儲每一個feature排序后對應的data的序列,也就是上圖最左邊的灰色方塊。Pre-sorted 算法需要的內存約是訓練數據的兩倍(2 * #data * #features* 4Bytes),因為xgboost既要保存原始feature的值,也要保存這個值的順序索引,這些值需要32位的浮點數來保存它需要用32位浮點來保存 feature value,并且對每一列特征,都需要一個額外的排好序的索引,這也需要32位的存儲空間。
2. 我們使用bin來表示feature,一般bin的個數都是控制在比較小的范圍內,這樣我們可以使用更少的Byte來存儲,如上圖,使用Byte來存,而原先的feature value可能是float,需要用4個Bytes來存儲。對于 histogram 算法,則只需要(#data* #features * 1Bytes)的內存消耗,僅為 pre-sorted算法的1/8。因為 histogram 算法僅需要存儲 feature bin value (離散化后的數值),不需要原始的 feature value,也不用排序,而 bin value 用 uint8_t (256 bins) 的類型一般也就足夠了。
當我們用數據的bin描述數據特征的時候帶來的變化:首先是不需要像預排序算法那樣去存儲每一個排序后數據的序列,也就是下圖灰色的表,在LightGBM中,這部分的計算代價是0;第二個,一般bin會控制在一個比較小的范圍,所以我們可以用更小的內存來存儲
b. 計算上的優勢
針對稀疏特征優化? 對于稀疏的特征只需要O(2 * 非零值的樣本個數)的時間復雜度來構造直方圖
計算上的優勢則主要體現在“數據分割”。決策樹算法有兩個主要操作組成,一個是“尋找分割點”,另一個是“數據分割”。從算法時間復雜度來看,Histogram 算法和 pre-sorted 算法在“尋找分割點”的代價是一樣的,都是O(#feature*#data)。而在“數據分割”時,pre-sorted 算法需要O(#feature*#data),而 histogram 算法是O(#data)。因為 pre-sorted 算法的每一列特征的順序都不一樣,分割的時候需要對每個特征單獨進行一次分割。Histogram算法不需要排序,所有特征共享同一個索引表,分割的時候僅需對這個索引表操作一次就可以。(更新:這一點不完全正確,pre-sorted 與 level-wise 結合的時候,其實可以共用一個索引表(row_idx_to_tree_node_idx)。然后在尋找分割點的時候,同時操作同一層的節點,省去分割的步驟。但這樣做的問題是會有非常多隨機訪問,有很大的chche miss,速度依然很慢。)
另一個計算上的優勢則是大幅減少了計算分割點增益的次數。對于一個特征,pre-sorted 需要對每一個不同特征值都計算一次分割增益 時間為(#data),而 histogram 直方圖算法只需要遍歷桶就行了,只需要計算 #bin (histogram 的橫軸的數量) 次。
最后,在數據并行的時候,用 histgoram 可以大幅降低通信代價。用 pre-sorted 算法的話,通信代價是非常大的(幾乎是沒辦法用的)。所以 xgoobst 在并行的時候也使用 histogram 進行通信。
histogram 算法也有缺點:
- 當然,Histogram算法并不是完美的。由于特征被離散化后,找到的并不是很精確的分割點,訓練誤差沒有 pre-sorted 好, 所以會對結果產生影響。但在不同的數據集上的結果表明,離散化的分割點對最終的精度影響并不是很大,甚至有時候會更好一點。原因是決策樹本來就是弱模型,分割點是不是精確并不是太重要;較粗的分割點也有正則化的效果,可以有效地防止過擬合;即使單棵樹的訓練誤差比精確分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下沒有太大的影響。
- 預處理能夠忽略零值特征,減少訓練代價;而直方圖不能對稀疏進行優化,只是計算累加值(累加梯度和樣本數)。但是,LightGBM 對稀疏進行了優化:只用非零特征構建直方圖。
LightGBM 為何使用直方圖這種比較粗的分割節點方法,還能達到比較好的效果?
雖然分割的精度變差了,但是對最后結果的影響不是很大,主要由于決策樹是弱模型, 分割點是不是精確并不是太重要 ;較粗的分割點也有正則化的效果,可以有效地防止過擬合;即使單棵樹的訓練誤差比精確分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下沒有太大的影響。
xgboost的近似直方圖算法也類似于lightgbm這里的直方圖算法,為什么xgboost的近似算法比lightgbm還是慢很多呢?
xgboost在每一層都動態構建直方圖, 因為xgboost的直方圖算法不是針對某個特定的feature,而是所有feature共享一個直方圖(每個樣本的權重是二階導),所以每一層都要重新構建直方圖,而lightgbm中對每個特征都有一個直方圖,所以構建一次直方圖就夠了。
3 帶深度限制的Leaf-wise的葉子生長策略
LightGBM使用了帶有深度限制的節點展開方法(Leaf-wise)來提高模型精度,這是比XGBoost中Level-wise更高效的方法。
它可以降低訓練誤差得到更好的精度。但是單純的使用Leaf-wise可能會生長出比較深的樹,在小數據集上可能會造成過擬合,因此在Leaf-wise之上多加一個深度限制. 它拋棄了大多數 GBDT 工具使用的按層生長(level-wise) 的決策樹生長策略,而使用了帶有深度限制的按葉子生長 (leaf-wise) 算法。 level-wise 過一次數據可以同時分裂同一層的葉子,容易進行多線程優化,不容易過擬合。
Level-wise(xgboost)過一次數據可以同時分裂同一層的葉子,容易進行多線程優化,也好控制模型復雜度,不容易過擬合。但實際上Level-wise是一種低效算法,因為它不加區分的對待同一層的葉子,帶來了很多沒必要的開銷,因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。
Leaf-wise是一種更為高效的策略:每次從當前所有葉子中,找到分裂增益最大的一個葉子,然后分裂,如此循環。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。
Leaf-wise的缺點:可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度限制,在保證高效率的同時防止過擬合。
4、直方圖做差優化
LightGBM還使用了直方圖做差的優化,達到了兩倍的加速。
可以觀察到:一個葉子節點的直方圖,可以由它的父親節點的直方圖減去它的兄弟節點的直方圖得到。
通常構造直方圖,需要遍歷該葉子上的所有數據,但直方圖做差僅需遍歷直方圖的 k 個桶。利用這個方法,LightGBM 可以在構造一個葉子的直方圖后,可以用非常微小的代價得到它兄弟葉子的直方圖,在速度上可以提升一倍。
根據這一點我們可以構造出來數據量比較小的葉子節點上的直方圖,然后用直方圖做差來得到數據量比較大的葉子節點上的直方圖,從而達到加速的效果。
5、 增加緩存命中率
預排序算法中有兩個頻繁的操作會導致cache-miss,也就是緩存消失(對速度的影響很大,特別是數據量很大的時候,順序訪問比隨機訪問的速度快4倍以上 ?)。
LightGBM使用的直方圖算法能很好的解決這類問題。首先。對梯度的訪問,因為不用對特征進行排序,同時,所有的特征都用同樣的方式來訪問,所以只需要對梯度訪問的順序進行重新排序,所有的特征都能連續的訪問梯度。并且直方圖算法不需要把數據id到葉子節點號上(不需要這個索引表,沒有這個緩存消失問題)
LightGBM使用直方圖算法則是天然的cache friendly,首先,對梯度的訪問,因為不需要對feature進行排序,同時,所有的feature都采用同樣的方式進行訪問,所以只需要對梯度訪問的順序進行一個重新的排序,所有的feature都能連續地訪問梯度。
此外,直方圖算法不需要數據id到葉子id的一個索引表,沒有這樣一個cache-miss的問題。事實上,在cache-miss這樣一個方面,對速度的影響是很大的,尤其在數據量很大的時候,MRSA研究人員進行過測試,在數據量很多的時候,相比于隨機訪問,順序訪問的速度可以快4倍以上,這其中速度的差異基本上就是由cache-miss而帶來的。
6、支持類別特征
傳統的機器學習一般不能支持直接輸入類別特征,需要先轉化成多維的0-1特征,這樣無論在空間上還是時間上效率都不高。LightGBM通過更改決策樹算法的決策規則,直接原生支持類別特征,不需要轉化,并且通過一些實驗,MRSA研究人員驗證了直接使用離散特征可以比使用0-1離散化后的特征,提高了近8倍的速度。
四 支持分布式(并行學習)
LightGBM提供以下并行學習算法的優化:特征并行、數據并行、投票并行。
LightGBM原生支持并行學習,特征并行(Featrue Parallelization)和數據并行(Data Parallelization),還有一種是基于投票的數據并行(Voting Parallelization)
- 特征并行的主要思想是在不同機器、在不同的特征集合上分別尋找最優的分割點,然后在機器間同步最優的分割點。
- 數據并行則是讓不同的機器先在本地構造直方圖,然后進行全局的合并,最后在合并的直方圖上面尋找最優分割點。
1 特征并行
特征并行算法目的是在決策樹生成過程中的每次迭代,高效地找到最優特征分裂點。特征并行的主要思想是在不同機器在不同的特征集合上分別尋找最優的分割點,然后在機器間同步最優的分割點。
傳統算法中的特征并行,主要是體現在找到最好的分割點,其步驟為:
傳統特征并行的缺點:
LightGBM中的并行特征
由于特征并行在訓練樣本的個數大的時候不能很好地加速,LightGBM做了以下優化:不是垂直分割數據,而是每個線程都擁有完整的全部數據。因此,LightGBM不需要為分割數據結果進行通信,因為每個線程都知道如何劃分數據。并且訓練樣本的個數不會變大,因此這種方案是合理的。
LightGBM中實現特征并行的過程:
但是這樣仍然有缺點:
因此,建議在數據量很大時使用數據并行。
?
2 數據并行
傳統算法數據并行旨在并行化整個決策學習。數據并行的過程是:
在第3步中,有兩種合并的方式:
- 采用點對點方式(point-to-point communication algorithm)進行通訊,每個worker通訊量為O(#machine?#feature?#bin)
- 采用collective communication algorithm(如“All Reduce”)進行通訊(相當于有一個中心節點,通訊后在返回結果),每個worker的通訊量為O(2?#feature?#bin)
可以看出通信的代價是很高的,這也是數據并行的缺點 通信成本高。如果使用點對點通信算法,則一臺機器的通信成本約為O(#machine * #feature * #bin)。如果使用聚合通信算法(例如“All Reduce”),通信成本約為O(2 * #feature * #bin)。
LightGBM中的數據并行
LightGBM中通過下面方法來降低數據并行的通信成本:
通過上述方法,LightGBM 將數據并行中的通訊開銷減少到O(0.5 * #feature * #bin)。
第一步,使用本地數據計算特征分桶,并將特征值壓縮為 int 桶號;
第二步,本地計算所有特征的直方圖,通過 reducescatter 得到每個 work 分配到的那兩個特征的全局直方圖;
第三步,每個 work 求出本地最優分裂(最優分裂節點,分裂的特征,以及特征的分裂閾值);通過全局歸約得到全局最優分裂;
第四步,每個 work 根據全局最優分裂對本地模型進行分裂。計算葉子節點的權重;
第五步,重新計算分裂出的葉子節點的直方圖,重復 2,3,4 步驟直到收斂;
?
分桶并行化
計算特征分桶是求直方圖的先決條件,給定每個特征要分成的桶數,計算每桶的特征值上下界。在分布式計算中,每個 work 計算自己負責的特征的 bin_mapper,之后再通過 allreduce 得到所有特征的 bin_mapper。最后可以根據 bin_mapper,將 float 的特征值映射到 bin 中,就可以用 int 桶編號來表示
?
直方圖并行化
本地建立所有特征的直方圖,每個特征直方圖可以通過遍歷已經編碼為 bin_id 的數據快速實現,最終得到 6 個直方圖,包含樣本數,以及樣本的一階二階導數之和。
合并全局直方圖,傳統的 xgboost 在這里使用一個 allreduce 操作使每個 work 都同步了 6 個全局直方圖。但實際上每個 worker 其實只需要關心自己分得的特征的直方圖,這里 lightGBM 對 AllReduce 操作進行優化,使用 ReduceScatter 算法,最終每個 worker 只得到自己分配到的特征的直方圖,有效的降低了數據通信量,提高了訓練效率.
舉例:4 個 worker,R0-R3,總共 8 個特征,每個 work 已經計算完本地直方圖,下面要進行合并直方圖。
通過遞歸調用,一半一半的進行歸約操作,優點是大大減少了通信量,不需要向 AllReduce 每次都需要傳遞所有的信息,這個通信量是巨大的,缺點是只能用于 2^k worker。
最佳分裂并行化
每個 worker 得到分配到的兩個的特征的全局直方圖之后,即開始在本地遍歷葉子節點和特征,計算本地的最大分裂增益及分列方式。采用 allgather+ 本地 reduce 操作得到全局最優分裂。
xgboost 通過 allreduce 方式計算全局最優分裂,而 lgb 采用 allgather+ 本地 reduce 操作得到全局最優分裂
?
?
整個 AllReduce 有兩個過程 bottom up 和 bottom down, 完成本地計算之后,我們需要把多個本地計算結果挑出全局最優特征,這個在 XGB 里面也是基于 all reduce 實現的。在 LGB 里面使用 all Gather。
假設我們有5個節點,
第一步: R1 給 R0,這個時候 R0 的 V0 是自己的,V1從 R1 拿的(R0有 V0, V1)
第二步: R2 同步給 R0,這個時候 R0 的 V0 是自己的,V2、V3 從 R2 拿的 (R0有 V0, V1, V2, V3)
第三步: 五個節點的內容 R0 知道了四個。最終通過補全的方式,比如 R4 把剩下的幾個結果一一補到對應的位置上去,通過這樣的過程,每個節點都知道整個集群里面我對應的結果是怎么樣。
第四步:然后在本地做一次 reduce 操作,這樣每個節點都知道全局的結果。
在存儲和計算上面,AllGather 和 AllReduce 相比有什么不一樣呢?
存儲上,左節點接收一個,右節點接收一個,累計的結果往上傳,看過 AllReduce 代碼后我們會發現這個只需要一份內存 +Buff 的空間,比較節約空間,AllGather 呢?只要有幾個節點,我就會存儲幾個結果;計算上,和 AllReduce 對比,少一次 BottomDown 廣播;綜上 AllGather 會更加吃內存、速度會更加快,而樹模型本身占的空間并不大,這個也是 AllGather 在樹模型上適用的原因
?
3 投票并行
LightGBM采用一種稱為PV-Tree的算法進行投票并行(Voting Parallel),其實這本質上也是一種數據并行
PV-Tree和普通的決策樹差不多,只是在尋找最優切分點上有所不同。
投票并行進一步降低了數據并行中的通信成本,使其減少至常數級別。它使用兩階段投票來降低特征直方圖的通信成本
可以看出,PV-tree將原本需要#feature×#bin 變為了2k×#bin,通信開銷得到降低。此外,可以證明,當每個worker的數據足夠多的時候,top-2k個中包含全局最佳切分點的概率非常高。
4 網絡通信的優化
在LightGBM的并行學習中,它只需要使用一些聚合通信算法,如“All reduce”,“All gather”和“Reduce scatter”。LightGBM實現了最先進的state-of-art算法。這些聚合通信算法可以提供比點對點通信更好的性能
[機器學習] LightGBM中常用并行計算算子原理以及在LightGBM中的具體實現
?
?
五、支持的應用和度量
1 應用
- 回歸,目標函數是L2損失
- 二進制分類,目標函數是logloss(對數損失)
- 多分類
- 交叉熵,目標函數是logloss,支持非二進制標簽的訓練
- lambdarank,目標函數為基于NDCG的lambdarank
2 度量
- L1 loss:絕對值損失
- L2 loss:MSE,平方損失
- Log loss:對數損失
- 分類錯誤率
- AUC(Area Under Curve):ROC曲線下的面積
- NDCG(Normalized Discounted Cumulative Gain):歸一化折損累積增益
- MAP(Mean Average Precision):平均精度均值
- 多類別對數損失
- 多類別分類錯誤率
- Fair損失
- Huber損失
- Possion:泊松回歸
- Quantile:分位數回歸
- MAPE(Mean Absolute Percent Error):平均絕對百分比誤差
- kullback_leibler:Kullback-Leibler divergence
- gamma:negative log-likelihood for Gamma regression
- tweedie:negative log-likelihood for Tweedie regression
- 更多閱讀原文
3 其他
- 限制樹的最大深度max_depth
- DART:Dropouts meet Multiple Additive Regression Trees
- L1 / L2正則化
- 套袋
- 隨即選擇列(特征)子集
- Continued train with input GBDT model
- Continued train with the input score file
- Weighted training
- Validation metric output during training
- 交叉驗證
- Multi metrics
- 提前停止(訓練和預測)
- Prediction for leaf index
?
參考:
https://fuhailin.github.io/LightGBM/
總結
以上是生活随笔為你收集整理的[机器学习] Boosting算法4 --- LightGBM介绍与分布式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: thinkpad t480和t490的区
- 下一篇: 中国有哪几个证券公司