效率和內存上的提升
1) 在訓練決策樹計算切分點的增益時,xgboost采用預排序,即需要對每個樣本的切分位置都要計算一遍,所以時間復雜度是O(#data)。
而LightGBM則是將樣本離散化為直方圖,直方圖算法的基本思想是先把連續的浮點特征值離散化成k個整數,同時構造一個寬度為k的直方圖。在遍歷數據的時候,根據離散化后的值作為索引在直方圖中累積統計量,當遍歷一次數據后,直方圖累積了需要的統計量,然后根據直方圖的離散值,遍歷尋找最優的分割點)
Histogram 算法的優缺點:
- Histogram算法並不是完美的。由於特征被離散化后,找到的並不是很精確的分割點,所以會對結果產生影響。但在實際的數據集上表明,離散化的分裂點對最終的精度影響並不大,甚至會好一些。原因在於decision tree本身就是一個弱學習器,采用Histogram算法會起到正則化的效果,有效地防止模型的過擬合。
- 時間上的開銷由原來的O(#data * #features)降到O(k * #features)。由於離散化,#bin遠小於#data,因此時間上有很大的提升。
- Histogram算法還可以進一步加速。一個葉子節點的Histogram可以直接由父節點的Histogram和兄弟節點的Histogram做差得到。一般情況下,構造Histogram需要遍歷該葉子上的所有數據,通過該方法,只需要遍歷Histogram的k個捅。速度提升了一倍。
這樣再計算分裂點增益時只需要根據直方圖切割位置計算即可,時間復雜度縮減為O(#bins),比如原始數據是100條,需要進行100次切割計算,如果分成10個直方圖之后,只需要進行10次分割計算即可,時間效率上大大提高了。直方圖算法是一種犧牲了一定的切分准確性而換取訓練速度以及節省內存空間消耗的算法。(初始構造直方圖是需要一次O(#data)的時間復雜度,不過這里只涉及到加和操作)
2)直方圖做差進一步提高效率,計算某一節點的葉節點的直方圖可以通過將該節點的直方圖與另一子節點的直方圖做差得到,所以每次分裂只需計算分裂后樣本數較少的子節點的直方圖然后通過做差的方式獲得另一個子節點的直方圖,進一步提高效率
3)節省內存
- 將連續數據離散化為直方圖的形式,對於數據量較小的情形可以使用小型的數據類型來保存訓練數據
- 不必像預排序一樣保留額外的對特征值進行預排序的信息
稀疏特征優化
對稀疏特征構建直方圖時的時間復雜度為O(2*#非零數據)
帶深度限制的Leaf-wise的葉子生長策略
Level-wise過一次數據可以同時分裂同一層的葉子,容易進行多線程優化,也好控制模型復雜度,不容易過擬合。但實際上Level-wise是一種低效的算法,因為它不加區分的對待同一層的葉子,帶來了很多沒必要的開銷,因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。
Leaf-wise則是一種更為高效的策略,每次從當前所有葉子中,找到分裂增益最大的一個葉子,然后分裂,如此循環。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。Leaf-wise的缺點是可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合。
直接支持類別特征
lightGBM可以直接用類別特征進行訓練,不必預先進行獨熱編碼,速度會提升不少,參數設置categorical_feature
來指定數據中的類別特征列。
對於類別類型特征我們原始的做法是進行獨熱編碼,但是這種做法對於基於樹的模型而言不是很好,對於基數較大的類別特征,可能會生成非常不平衡的樹並且需要一顆很深的樹才能達到較好的准確率;比較好的做法是將類別特征划分為兩個子集,直接划分方法眾多(2^(k-1)-1),對於回歸樹而言有一種較高效的方法只需要O(klogk)的時間復雜度,基本思想是對類別按照與目標標簽的相關性進行重排序,具體一點是對於保存了類別特征的直方圖根據其累計值(sum_gradient/sum_hessian)重排序,在排序好的直方圖上選取最佳切分位置。
特征並行減少通信傳輸代價
特征並行是為了將尋找決策樹的最佳切分點這一過程並行化
- 傳統做法
- 對數據列采樣,即不同的機器上保留不同的特征子集
- 各個機器上的worker根據所分配的特征子集尋找到局部的最優切分點(特征、閾值)
- 互相通信來從局部最佳切分點里得到最佳切分點
- 擁有最佳切分點的worker執行切分操作,然后將切分結果傳送給其他的worker
- 其他的worker根據接收到的數據來切分數據
- 傳統做法的缺點
- 計算量太大,並沒有提升切分的效率,時間復雜度為O(#data)(因為每個worker持有所有行,需要處理全部的記錄),當數據量較大時特征並行並不能提升速度
- 切分結果的通信代價,大約為O(#data/8)(若一個數據樣本為1bit)
- LightGBM的做法
讓每個機器保留整個完整的數據集(並不是經過列采樣的數據),這樣就不必在切分后傳輸切分結果數據,因為每個機器已經持有完整的數據集- 各個機器上的worker根據所分配的特征子集尋找到局部的最優切分點(特征、閾值)
- 互相通信來從局部最佳切分點里得到最佳切分點
- 執行最優切分操作
Notes:典型的空間換時間,差別就是減少了傳輸切分結果的步驟,節省了這里的通信消耗
數據並行
上述特征並行的方法並沒有根本解決尋找切分點的計算效率問題,當記錄數過大時需要考慮數據並行的方法
- 傳統做法
- 行采樣,對數據進行橫向切分
- worker使用分配到的局部數據構建局部的直方圖
- 合並局部直方圖得到全局的直方圖
- 對全局直方圖尋找最優切分點,然后進行切分
- 缺點:通信代價過高,若使用point-to-point的通信算法,每個機器的通信代價時間復雜度為O(#machine*#feature*#bin),若使用collective通信算法則通信代價為O(2*#feature*#bin)
- LightGBM的做法(依然是降低通信代價)
- 不同於合並所有的局部直方圖獲得全局的直方圖,LightGBM通過Reduce Scatter方法來合並不同worker的無交叉的不同特征的直方圖,這樣找到該直方圖的局部最優切分點,最后同步到全局最優切分點
- 基於直方圖做差的方法,在通信的過程中可以只傳輸某一葉節點的直方圖,而對於其鄰居可通過做差的方式得到
- 通信的時間復雜度為O(0.5*#feature*#bin)