1. 程式人生 > >對LightGBM的一點理解

對LightGBM的一點理解

LightGBM是微軟團隊2017年發表在NIPS的一篇論文,也是一種基於GBDT的Boosting的方法。之前有了各種Boosting方法,以及在各類資料比賽中大放異彩的XGBoost,LightGBM的優勢在哪裡呢?

LightGBM是一種基於GBDT的提升方法。對於這類基於樹的模型,最耗時的部分就是在進行特徵選擇結點分裂時,需要遍歷所有可能的劃分點,計算資訊增益,從而找到最優的劃分點。前面雖然有了各類的演算法對這個過程進行優化,比如XGBoost,但是在特徵維數很高,樣本量很大的情況下,它的效率和靈活性還是不夠好。因此,本文的作者提出了LightGBM這個模型,極大的提升了計算效率。根據論文裡的說法,在模型精度和GBDT差不多的情況下訓練速度比它快了20倍。所以,LightGBM這個模型的提出,所要解決的主要問題是計算效率的問題。在快的同時,還能保證模型的精度,這是它最大的優點。

為了讓GBDT快起來,入手的方向只有兩個,要不就減少特徵數,這樣在進行特徵選擇結點分裂的時候能夠減少計算量,提高速度;要不就減少訓練樣本數,這樣也能減少計算量,提高效率。但是這樣做缺點很明顯,犧牲了模型的精度啊!有沒有什麼兩全其美的方法呢?

在介紹LightGBM的方法之前,我們先回顧一下之前的一些模型是怎麼做的。
對於一些採用行取樣進行加速的模型,根據的是樣本的權重進行的取樣(比如AdaBoost模型,在訓練過程中會提升那些之前被誤分類的樣本的權重),但是對與GBDT來說這就不適用了,因為它的樣本是沒有權重的;不需要利用樣本權重的模型,比如SGD(隨機梯度提升),通過隨機行取樣的方式減少計算量,雖然可以應用到GBDT,但是顯然會損失模型的精度。

對於列取樣過程中的優化,比如隨機森林,並不對所有的特徵都做計算,而是隨機選擇幾個特徵,從這裡面選擇最優的屬性,減小了計算量。

本文的優化方法,就是在行取樣和列取樣兩個方面,提出了更勝一籌的優化方法,從而在不犧牲精度的條件下,極大的提升了訓練速度!

  • 針對行取樣的優化,提出了GOSS(Gradient-based One-side Sampling)
  • 針對列取樣,提出了EFB(Exclusive Feature Bundling)

GOSS

LigntGBM也好,XGBoost也好,都是提升方法,基於GBDT,建樹的過程是序列化的過程,所以在Tree層面上是不能夠並行化處理的。可以進行加速提升的部分,就是在進行特徵選擇結點分裂的時候,而這也是建樹中最耗時的部分。比較常用的優化方法,一種是對特徵值先進行排序,然後計算每個劃分點的增益,存起來,最後通過查表比較的方式進行選擇,相當於用空間換時間;還有就是基於直方圖的方法。XGBoost中提供了這兩種方法的實現。
而本文呢,是注意到在訓練過程中,如果一個樣本產生的梯度很小,說明它的訓練誤差很小,基本上是well-trained的。這就為行取樣提供了一個依據,選擇那些梯度大的樣本進行訓練,對於梯度小的可以drop掉。但是這樣會帶來一個問題,改變了訓練樣本的分佈。GOSS呢,就提出不把這些梯度小的捨棄掉,而是設定一個取樣比例,留下一部分,但是為了彌補丟掉的那一部分的資料在計算增益時的作用,對這些留下的小梯度的樣本乘個係數。
舉個例子:整個訓練樣本大小為100,當計算完梯度之後,對每個樣本的梯度絕對值按從大到小排序,假如設定a的比例,作為梯度大的資料,這部分的集合記作A,剩下的就是認為梯度小的比例,在這基礎上,再乘b,隨機選擇這麼多的小梯度的樣本加入到訓練集中。不過在計算增益的時候要對這些小梯度的樣本乘個係數

1 a b 作為放大,彌補取樣的缺失。通過採用這種方法,既減少了訓練樣本,提高了模型對那些還沒有訓練好的樣本的關注,又在一定程度上使得近似值與精確計算值很接近,不損失精度。
演算法過程如下:
這裡寫圖片描述

EFB

EFB主要是從列取樣的角度。但並不是真正的取樣,因為它降低了列向量的維度,但並不是通過取樣的方式得到的,而是通過對feature也構建直方圖,然後合併那些exclusive的特徵,從而達到減少列向量的目的。
這裡有兩個關鍵問題:

  • 如何確定哪些特徵需要bundle?
  • 如何bundle?
    它的前提假設是說通常高維的資料往往也是稀疏的,在稀疏的特徵空間中,許多特徵之間通常是互斥的,可以將這些特徵合併成一個特徵
    演算法流程如下:
    這裡寫圖片描述

其他

看LightGBM的Github,有提到它是一種帶深度限制的Leaf-wise的葉子生長策略(在論文裡死活也沒找到····),與之相比,XGBoost是一種Level-wise的方式。具體解釋是說:

  • Level-wise過一次資料可以同時分裂同一層的葉子,容易進行多執行緒優化,也好控制模型複雜度,不容易過擬合。但實際上Level-wise是一種低效演算法,因為它不加區分的對待同一層的葉子,帶來了很多沒必要的開銷,因為實際上很多葉子的分裂增益較低,沒必要進行搜尋和分裂。
  • Leaf-wise則是一種更為高效的策略:每次從當前所有葉子中,找到分裂增益最大的一個葉子,然後分裂,如此迴圈。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。
  • Leaf-wise的缺點:可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度限制,在保證高效率的同時防止過擬合。
  • 參考這裡:12