LightGBM簡介
- 簡介
基於GBDT的梯度提升決策樹模型LGB,是GBDT的一種高效實現,可xgb的原理基本一致,主要都采用損失函數的梯度下降 方向作為當前決策樹的殘差近似值,去擬合新的決策樹。 - 優勢
LightGBM具有更快的訓練效率, 低內存的使用,支持並行化學習,可以處理大規模(海量)的數據,支持支持使用category特征 - 速度提升
實驗數據: 比xgb快了將近10倍,內存占用率大約為xgb的1/6,並且准確率也有提升.
xgboost的優缺點
01 xgboost 精確貪心算法
每輪迭代時,都需要遍歷整個訓練數據多次;需要把整個數據集裝進內存中。
優點: 可以找到精確的划分條件
缺點: 計算量巨大,內存占用也巨大,易產生過擬合
02 xgboost Level-wise(水平的)迭代方式
預排序的方法(pre-sorted):首先空間消耗大——保存了預排序后的結果,需要多消耗內存;其次,在遍歷每一個分割點的時候,都需要進行分裂增益的計算,消耗的代價大。
優點: 可以使用多線程,可以加速精確的貪心算法!!
缺點:效率低下,會產生不必要的葉子結點;並且,存在大量無用計算
03 XGBoost對cache優化不友好的幾點解釋
特征對梯度(預排序后的結果)是一種隨機訪問(順序訪問,在磁盤中是隨機訪問的定義),並且不同的特征訪問的順序不一樣,無法對cache進行優化;
(注:cache在內存中是按頁(一塊一塊)來進行划分的)
想要命中不同的特征的cache,需要進行不同的隨機訪問;
並且不同特征的訪問順序也不一致,也會造成較大的cache miss
LightGBM相較於xgboost優化了哪些方面
LGB主要設計特征
- 基於直方圖的決策樹算法
- 帶深度限制的Leaf-wise(按帶深度限制的按葉子結點的生成方式)的葉子生成策略
- 直方圖加速:做差進行加速
- Cache 命中率進行優化
- 直接支持類別特征(categorical Feature)
- 基於直方圖的稀疏特征優化
- 多線程優化
決策樹算法的差異 XGBoost VS LightGBM
決策樹算法 -> 改進
XGBoost使用的是pre-sorted算法,能夠更精確的找到數據分隔點。(代價:預排序需要兩倍的內存,遍歷每一個分割點,都需要進行增益計算,慢)
LightGBM使用的是直方圖算法,步驟:將連續的浮點特征離散成K個離散值,構造寬度為k的直方圖,遍歷訓練數據,統計每個離散值在直方圖中的累計統計量;
在進行選擇的時候,只需要根據直方圖的離散值,遍歷尋找最優的分割點。

LightGBM內存可以降為之前的1/8
之前需要int_32位來進行存儲,現在int_8位就可以了
計算代價得到降低
預排序: O(#data#features)。
直方圖: k個特征——也就是bin的分箱個數, O(#bin#features)。
直方圖算法的缺陷
直方圖算法的思想也很簡單,首先將連續的浮點數據轉換為bin數據,具體過程是首先確定對於每一個特征需要多少的桶bin,然后均分,將屬於該桶的樣本數據更新為bin的值,最后用直方圖表示。
- 使用bins替代了原數據, 相等於增加了正則化** (正則化的值越大,則模型越簡單)**
- 放棄了部分細節,導致很多數據的細節特征消失了,相似的數據就可能會被分到同一個桶內
- 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個桶即可。速度提升了一倍。
決策樹生長策略
- 進一步優化,不再使用按層生成的算法,而是按帶深度限制的按葉子結點的生成方式
- XGBoost采用的是按層生長level(depth)-wise生長策略,能夠同時分裂同一層的葉子,從而進行多線程優化,不容易過擬合;但不加區分的對待同一層的葉子,帶來了很多沒必要的開銷。因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。
- LightGBM采用leaf-wise生長策略,每次從當前所有葉子中找到分裂增益最大(一般也是數據量最大)的一個葉子,然后分裂,如此循環。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。Leaf-wise的缺點是可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合。
直方圖差加速
- LightGBM另一個優化是Histogram(直方圖)做差加速。
一個容易觀察到的現象:一個葉子的直方圖可以由它的父親節點的直方圖與它兄弟的直方圖做差得到。
通常構造直方圖,需要遍歷該葉子上的所有數據,但直方圖做差僅需遍歷直方圖的k個桶。
利用這個方法,LightGBM可以在構造一個葉子的直方圖后,可以用非常微小的代價得到它兄弟葉子的直方圖,在速度上可以提升一倍。
直接支持類別特征
- 常規:實際上大多數機器學習工具都無法直接支持類別特征,一般需要把類別特征,轉化one-hotting特征,降低了空間和時間的效率
- LGB:LightGBM優化了對類別特征的支持,可以直接輸入類別特征,不需要額外的0/1展開;lgb還在決策樹算法上增加了類別特征的決策規則。
one-hot編碼是處理類別特征的一個通用方法,然而在樹模型中,這可能並不一定是一個好的方法,尤其當類別特征中類別個數很多的情況下。主要的問題是:
- 浪費:可能存在浪費了某一個特征,使用ine-hot編碼后,在每一個決策結點上,要么選擇這個枚舉的特征值或者不選擇。
- 切分收益很低:當類別值很多時,每個類別上的數據可能會比較少,這時候切分會產生不平衡,這意味着切分增益也會很小(比較直觀的理解是,不平衡的切分和不切分沒有區別)。
- 會影響決策樹的學習。決策樹學習時利用的是統計信息,在這些數據量小的空間上,統計信息不准確,學習會變差。
LGB支持求解類別特征的最優切分的流程
- 離散特征建立直方圖:統計、排序、過濾、bins容器
- 計算分裂閾值的過程:
- 先看該特征下划分出的bin容器的個數,少的話(4個以下),直接逐個掃描
- 對於bin容器較多的情況, 先進行過濾,只讓子集合較大的bin容器參加划分閾值計算, 對每一個符合條件的bin容器進行公式計算(公式如下: 該bin容器下所有樣本的一階梯度之和/該bin容器下所有樣本的二階梯度之和 + 正則項(參數cat_smooth),得到一個值,根據該值對bin容器從小到大進行排序,然后分從左到右、從右到左進行搜索,得到最優分裂閾值。
- LightGBM中對離散特征實行的是many vs many 策略,這32個bin中最優划分的閾值的左邊或者右邊所有的bin容器就是一個many集合,而其他的bin容器就是另一個many集合。
- 對於連續特征,划分閾值只有一個,對於離散值可能會有多個划分閾值,每一個划分閾值對應着一個bin容器編號,當使用離散特征進行分裂時,只要數據樣本對應的bin容器編號在這些閾值對應的bin集合之中,這條數據就加入分裂后的左子樹,否則加入分裂后的右子樹。
LGB直接支持高效並行
- 支持特征並行:是在不同機器在不同的特征集合上分別尋找最優的分割點,然后在機器間同步最優的分割點
- 通過在本地保存全部數據避免對數據切分結果的通信 - 支持數據並行:讓不同的機器先在本地構造直方圖,然后進行全局的合並,最后在合並的直方圖上面尋找最優分割點。
- 使用分散規約(Reduce scatter)把直方圖合並的任務分攤到不同的機器,降低通信和計算,並利用直方圖做差,進一步減少了一半的通信量。
網絡通信優化
XGBoost由於采用pre-sorted算法,通信代價非常大,所以在並行的時候也是采用histogram算法;LightGBM采用的histogram算法通信代價小,通過使用集合通信算法,能夠實現並行計算的線性加速。
LightGBM原理
論文地址:LightGBM A Highly Efficient Gradient Boosting (https://papers.nips.cc/paper/6907-lightgbm-a-highly-efficient-gradient-boosting-decision-tree.pdf)
對比:
普通的GBDT、XGB:信息增益、預排序,計算信息增益需要掃描所有樣本,從而找到最優划分點。在面對大量數據或者特征維度很高時,它們的效率和擴展性很難使人滿意。
微軟開源的LightGBM(基於GBDT的)包含兩個算法:
- 單邊梯度采樣,Gradient-based One-Side Sampling(GOSS)
- GOSS(從減少樣本角度):排除大部分小梯度的樣本,僅用剩下的樣本計算信息增益。
- 梯度大的實例對信息增益有更大的影響,因此在下采樣時,我們應該盡量保留梯度大的樣本(預先設定閾值,或者最高百分位間),隨機去掉梯度小的樣本。 - 互斥特征綁定,Exclusive Feature Bundling(EFB)
- 捆綁互斥特征,也就是他們很少同時取非零值(也就是用一個合成特征代替)。通常真是應用中,雖然特征量比較多,但是由於特征空間十分稀疏,是否可以設計一種無損的方法來減少有效特征呢?特別在稀疏特征空間上,許多特征幾乎是互斥的(例如許多特征不會同時為非零值,像one-hot),我們可以捆綁互斥的特征。最后,我們將捆綁問題歸約到圖着色問題,通過貪心算法求得近似解。
- EBF的算法步驟如下:
- 將特征按照非零值的個數進行排序
- 計算不同特征之間的沖突比率
- 遍歷每個特征並嘗試合並特征,使沖突比率最小化
如何使用LightGBM
LightGBM調參指導
針對 leaf-wise 樹的參數優化:
- num_leaves:控制了葉節點的數目。它是控制樹模型復雜度的主要參數。
- 如果是level-wise,則該參數為2depth,其中depth為樹的深度。但是當葉子數量相同時,leaf-wise的樹要遠遠深過level-wise樹,非常容易導致過擬合。因此應該讓num_leaves小於2depth。在leaf-wise樹中,並不存在depth的概念。因為不存在一個從leaves到depth的合理映射。
- min_data_in_leaf:每個葉節點的最少樣本數量。它是處理leaf-wise樹的過擬合的重要參數。將它設為較大的值,可以避免生成一個過深的樹。但是也可能導致欠擬合。
- max_depth: 控制了樹的最大深度。該參數可以顯式的限制樹的深度。
針對更快的訓練速度:
- 通過設置 bagging_fraction 和 bagging_freq 參數來使用 bagging 方法
- 通過設置 feature_fraction 參數來使用特征的子抽樣
- 使用較小的 max_bin
- 使用 save_binary 在未來的學習過程對數據加載進行加速
獲取更好的准確率:
- 使用較大的 max_bin (學習速度可能變慢)
- 使用較小的 learning_rate 和較大的 num_iterations
- 使用較大的 num_leaves (可能導致過擬合)
- 使用更大的訓練數據
- 嘗試 dart
緩解過擬合:
- 使用較小的 max_bin
- 使用較小的 num_leaves
- 使用 min_data_in_leaf 和 min_sum_hessian_in_leaf
- 通過設置 bagging_fraction 和 bagging_freq 來使用 bagging
- 通過設置 feature_fraction 來使用特征子抽樣
- 使用更大的訓練數據
- 使用 lambda_l1, lambda_l2 和 min_gain_to_split 來使用正則
- 嘗試 max_depth 來避免生成過深的樹