【集成学习系列教程5】LightGBM
文章目錄
- 7 LightGBM
- 7.1 概述
- 7.2 LightGBM優化算法詳解
- 7.2.1 GOSS算法
- 7.2.2 EFB算法
- 7.2.3 Histogram算法
- 7.2.4 Leaf-Wise策略
- 7.2.5 直接支持類別型特征
- 7.2.6 并行優化方法
- 7.2.7 小結
- 7.3 LightGBM的使用
- 7.3.1 常用參數
- 7.3.2 常用調參方法
7 LightGBM
7.1 概述
前面我們介紹了AdaBoost和GBDT這兩種Boosting方法,它們已經在很多問題上發揮了強大的威力,也已經具有較好效率。但是,如今的數據集正在朝著樣本數越來越巨大,特征維度也越來越高的方向發展,此時這兩種傳統的Boosting方法在效率和可擴展性上已經不能滿足現在的需求了。主要原因是:傳統的Boosting算法中的基學習器需要通過對所有樣本點的每一個特征都進行掃描來計算信息增益,進而找到最佳的分割點,這在樣本數和特征數巨大的情況下會相當耗時。為了解決傳統Boosting方法在大樣本、高緯度數據的環境下的耗時問題,微軟團隊提出了兩種新的技術:基于梯度的單邊采樣(Gradient-based One-Side Sampling, GOSS)和互斥特征捆綁(Exclusive Feature Bundling, EFB)。下面簡單介紹下這兩種方法的原理。
-
GOSS:不再對所有的樣本都計算信息增益,而是采取“保留所有大梯度樣本,而對小梯度樣本進行隨機采樣”的方式,減少了計算信息增益的樣本數,降低了運算的復雜度,又不會對數據集的總體分布造成太大的破壞。這就是基于梯度的單邊采樣方法的基本思想。
-
EFB:將某些互斥性較大的特征捆綁成一個新的特征來降低特征的維度,使得找到最佳分割點的時間大大減少?;コ馓卣饕话闶轻槍Ω呔S度特征而言的,指的是幾乎不會同時取非零值的一組(兩個或兩個以上)特征。具體示例如下表所示:
樣本x1\boldsymbol x_1x1?樣本x2\boldsymbol x_2x2?樣本x3\boldsymbol x_3x3?樣本x4\boldsymbol x_4x4?樣本x5\boldsymbol x_5x5?…樣本xm?1\boldsymbol x_{ m-1}xm?1?樣本xm\boldsymbol x_mxm? 特征f1f_1f1? 1 3 0 0 8 … 0 5 特征f2f_2f2? 0 0 5 9 0 … 2 0
上表模擬了在大樣本、高維度數據集中兩個特征的分布情況,這兩個特征就組成了一組互斥特征。在大樣本、高維度數據集中,特征的分布一般都比較稀疏,也就是說會出現很多樣本在某些特征上取0值的情況。我們通過一定的策略找到在所有的樣本中都不會同時取非0值,或者同時取非0值的樣本很少的多個特征,將它們捆綁成一個特征,這樣可以在降低特征維度的同時又不會對數據集的分布造成太大的破壞。這就是互斥特征捆綁方法的思想。
?回顧前面介紹的GBDT算法,可以發現,GBDT算法在訓練每棵提升樹的時候有兩種提供樣本方式:第一種是為每棵樹都提供所有的樣本進行訓練,第二種是采用子采樣方式,按照固定比例無放回地取出一部分樣本依次給每棵提升樹訓練。使用第一種方法會導致如下問題:當數據集樣本數很多、特征維數很高的時候,為每棵樹都提供所有數據集中的樣本進行訓練會非常耗時。為了解決這一問題,我們可以在GBDT算法的基礎上使用GOSS和EFB這兩種方法。通過GOSS方法對基決策樹的訓練樣本進行靈活限制,再通過EFB方法對高維的特征空間進行降維,雙管齊下,這樣就能在很大程度上減少模型擬合數據集的時間,同時又不會降低準確率。我們將結合了GOSS方法和EFB方法的GBDT算法稱為LightGBM算法。可以用如下公式通俗地表示:
LightGBM=GBDT+GOSS+EFBLightGBM=GBDT+GOSS+EFB LightGBM=GBDT+GOSS+EFB
這就是LightGBM算法的由來。
7.2 LightGBM優化算法詳解
上一小節我們簡要介紹了GOSS和EFB這兩種算法的思路,并通過一條通俗的公式說明了LightGBM算法的來源 。本小節我們將對LightGBM中涉及的優化算法的細節進行闡述。
7.2.1 GOSS算法
前面我們介紹了AdaBoost算法,該算法的大體思想是:在每次迭代時更加注重上一次錯分的樣本點,增大上一次分錯的樣本的權重。雖然GBDT算法中并沒有這種為分錯樣本增大權重的機制,但是由于GBDT是以樣本的殘差(即模型對樣本的訓練結果與標簽值之間的差距)作為訓練提升樹的依據,所以GBDT算法可以根據每個樣本的殘差來判斷模型對樣本的擬合程度。在這里我們將殘差稱為梯度,那么按照梯度大小,數據集中的樣本就分為大梯度樣本和小梯度樣本兩種。
- 大梯度樣本一般是未經模型擬合或者模型欠擬合的樣本,模型對這些樣本訓練偏差較大,所以這些樣本是要在后續模型訓練中重點關注的樣本,應全部保留;
- 小梯度樣本一般是已經被模型擬合過、并且擬合得比較好的樣本,模型對這些樣本的訓練誤差較小,因此可以弱化對這些樣本的訓練,一個簡單粗暴的辦法就是直接拋棄掉這部分梯度較小的樣本,但這樣會對數據集的總體分布造成較大的破壞,所以還是不能完全忽略這部分樣本,而是對這部分樣本采取隨機采樣的方式。
GOSS算法對上面這兩點進行了實現。具體如下:
設當前模型為modelmodelmodel,訓練數據集為 III,迭代次數為ddd,大梯度樣本的采樣率為aaa,小梯度樣本的采樣率為bbb,損失函數為losslossloss,弱學習器的類型為LLL(一般為決策樹)。
循環進行ddd輪迭代,循環體中的各個步驟如下:
不斷重復循環體中的步驟,直到達到規定的迭代次數ddd或者losslossloss收斂為止。
? 從上面的步驟中可以看到,當a=0a=0a=0時,GOSS算法退化為隨機采樣算法;當a=1a=1a=1時,GOSS算法退化為傳統的取所有訓練樣本對弱學習器進行訓練的方法。訓練出的模型精確度要高于隨機采樣算法。
GOSS算法具有如下優點:
- 對樣本進行采樣增加了弱學習器的多樣性,從而提升了模型的泛化能力;
- 該算法幾乎不會對數據集的分布造成破壞,同時又大幅度減少了每一輪迭代的訓練樣本數,所以該算法在保證了GBDT模型的精度不受損失的同時,又大大減少了GBDT模型對數據集的擬合時間。
7.2.2 EFB算法
前面我們已經簡單介紹了EFB算法的原理,即將多個不同的特征按照互斥的程度劃分為了更小的互斥捆綁數,從而實現了特征降維。但由于現實中的數據集很多是大樣本、高維度的數據集,遍歷所有特征在各個樣本上的值尚且非常耗時了,更不用說為了匹配互斥特征還要進行重復遍歷,所以找到各組互斥的特征并進行捆綁是一個NP-hard問題,即在多項式時間內不可能找到確切的解。為了解決這一問題,EFB算法在原有特征互斥判定方法的基礎上進行了如下改進:用一個稱為最大沖突數的參數來量化并限制同一個特征捆中總的互斥程度,我們允許特征之間存在少數樣本不互斥,即允許存在某些特征對應的樣本之間不同時取非零值。這樣做放寬了特征互斥的條件,減少了特征捆綁數,從而進一步的提高了計算的有效性。理論上,使用該方法對模型準確率的影響程度為O([(1?γ)n]?23)O([(1-\gamma)n]^{-\frac{2}{3}})O([(1?γ)n]?32?),參數γ\gammaγ稱為每個綁定的最大沖突率,用來量化不同特征之間的互斥程度。當γ\gammaγ取值較小時,可以在精確度和模型訓練效率上獲得很好的權衡。EFB算法實現該功能的具體步驟如下:
初始化各變量:構造一個帶權圖GGG,圖中結點代表各個不同的特征,邊的權值代表對應特征之間的互斥程度(沖突數),通過各個特征節點在圖GGG中的度(即與特征節點相連的邊數)降序排序所有特征,并按順序加入到列表FeaturesFeaturesFeatures中。設特征數為FFF,特征捆中的最大沖突數為KKK,特征捆列表為bundlesbundlesbundles(如bundles[i]bundles[i]bundles[i]表示構建出的第iii捆特征,初始化狀態下所有bundles[i]bundles[i]bundles[i]均為空),bundlesConflictsbundlesConflictsbundlesConflicts列表記錄bundlesbundlesbundles中各個特征捆的當前總沖突數(如bundlesConflicts[i]bundlesConflicts[i]bundlesConflicts[i]表示第iii捆特征的總沖突數)。
接下來進行FFF次循環。循環體中的步驟如下:
- 如果加入新特征Features[i]Features[i]Features[i]后bundles[j]bundles[j]bundles[j]的總沖突數小于KKK,則將該特征加入bundles[j]bundles[j]bundles[j];
- 如果加入之后大于KKK,則將新特征Features[i]Features[i]Features[i]加入下一個空的特征捆bundles[j+1]bundles[j+1]bundles[j+1]中。
不斷重復上述步驟,直至遍歷完所有特征,最終輸出bundlesbundlesbundles。
上述算法的時間復雜度為O(n_features2)O(n\_features^2)O(n_features2)(n_featuresn\_featuresn_features為總的特征數),在特征維度不是很大時,這樣的復雜度是可以接受的,但當樣本維度較高時,這種方法就顯得非常低效。對此,微軟團隊又提出的另外一種更加高效的算法:不再按照特征節點度的大小的降序來對特征進行排序,而是按特征中非零值數量的降序來對特征進行排序,因為非零值更多的特征通常會導致更高的沖突概率。通過這一點小小的改變,EFB算法的復雜度得到了進一步下降。
7.2.3 Histogram算法
我們通過EFB算法成功將所有特征拆分成了多個互斥的特征捆,但要怎么將同一特征捆中的所有特征合并起來呢?Lightgbm中使用直方圖(Histogram)算法來合并互斥特征。直方圖算法的直觀示意圖如下:
如圖,該算法的基本思想為:
由于直方圖算法的思想是存儲離散的bins而不是連續的特征值,所以我們可以通過讓互斥特征駐留在不同的bins中來構造特征捆。這可以通過在原始特征值的基礎上增加適當的偏移量來實現。比如,假設我們有兩個特征A和B,A的取值范圍是[0,10),而B的取值范圍是[0,20),我們可以通過給B增加偏移量10,使得B的取值范圍變成[10, 30),這樣就可以合并特征A和B的范圍區間,形成取值范圍為[0,30)的新特征來取代原來的A和B。使用直方圖算法在規避了對特征進行排序、從而減小了損耗時間的同時,又實現了對互斥特征進行合并、從而實現了特征降維的目的,一舉兩得。
7.2.4 Leaf-Wise策略
在LightGBM算法之前,大部分以決策樹為基學習器的集成學習方法(包括原始GBDT算法、XGBoost算法等)都是通過一種稱為Level-Wise的策略來生成基決策樹。這種生成策略的缺點是:對于同一深度的的所有節點都不加區分地進行分裂,使得很多分裂增益較低的節點也進行了分裂,從而帶來了沒必要的開銷。示意圖如下:
為了避免帶來不必要的開銷,LightGBM使用了一種稱為Leaf-Wise的樹生成策略。該策略的思路為:每次只從同一深度的所有節點中找到分裂增益最大的那一個節點進行分裂而不對其他節點進行分裂,如此循環,直到到達所設定的最大深度為止。示意圖如下:
在分裂次數相同的情況下,相比使用Level-Wise策略,使用Leaf-Wise策略可以得到更好的精度。但是,當樣本量較小的時候,Leaf-Wise很容易造成過擬合。 所以,可以通過調整LightGBM中的參數 max_depth 來限制樹的最大深度,避免過擬合。
7.2.5 直接支持類別型特征
所謂類別型特征(Categorical features)是指其值是離散的集合且相互比較并無意義的變量,比如用戶的ID、產品ID、顏色等。 這些變量無法在二叉決策樹當中直接使用。 常規的做法是將這些類別變量通過預處理的方式轉化成數值型變量再喂給模型,比如用一個或者若干個數值來代表一個類別型特征。目前廣泛用于類別特征的處理方法是One-Hot編碼:將原來的特征刪除,然后對于每一個類別加一個0/1的用來指示是否含有該類別的數值型特征。使用這種處理方式有一個致命的缺點:在高勢特征(也叫高數量類別特征,即對于某個類別型特征,不同值的數量非常多)當中,比如用戶的ID,用這種編碼方式生成的特征維數會非常巨大,造成維度災難。
? 在實際應用中,大多數機器學習算法模型都無法直接支持對類別特征的使用,一般需要把類別特征通過One-Hot編碼的方式轉化到高維的0/1 特征空間,這樣做降低了機器學習模型擬合數據集的空間和時間的效率。而如果能直接使用類別特征,避開類別特征編碼,那么就可以提升機器學習算法的整體效率。基于這個考慮,LightGBM實現了對類別特征的支持,也就是說,LightGBM模型支持對類別特征的直接讀取,而不需要讀取類別特征的One-Hot編碼形式。這使得LightGBM模型的效率有了進一步的提升。
7.2.6 并行優化方法
LightGBM中還采用了并行優化方法,進一步提升了模型擬合的效率。它的并行優化方法是基于特征并行和數據并行這兩種普通的并行方法進行改進的。這兩種方法的主要思想如下:
- 特征并行:使用多個不同的機器,分別在不同特征集合上尋找最優的分割點,然后再對所有機器結果進行同步,輸出最優分割點;
- 數據并行:讓不同的機器先在本地各自構造特征直方圖,然后進行全局合并,最后在合并的直方圖上尋找最優分割點。
LightGBM針對這兩種并行方法都做了優化:
- 在特征并行方法中,各個機器均保存數據集中的全部數據,“各取所需”,避免因數據量不足造成不同機器數據分割結果的相互干擾;
- 在數據并行方法中,使用一種稱為分散規約 (Reduce scatter)的方法把直方圖合并的任務分攤到不同的機器,減少了單個機器的計算負擔,并利用直方圖做差的方式減少了一半的通信量。
7.2.7 小結
1.7.2小節中我們介紹了LightGBM中所用到的優化算法,這些方法在原始GBDT算法的基礎上大幅提升運算速度,同時保持了和原始GBDT算法幾乎一致的準確率,從而解決了原始GBDT算法在大樣本、高維度數據集上效率過慢的問題,這使得LightGBM算法在近兩年來得到了廣泛的應用。
7.3 LightGBM的使用
令人感到可惜的是,sklearn中并沒有為用戶提供調用LightGBM算法模型的接口,因為LightGBM是微軟團隊的研究成果,它們自己編寫了一個獨立的庫供用戶使用LightGBM算法。盡管如此,sklearn還是巧妙借鑒了LightGBM算法的思想,在GBDT算法的基礎上進行了改進,設計出了基于直方圖算法進行改進的GBDT算法,并提供了HistGradientBoostingClassifier和HistGradientBoostingRegressor這兩個接口供用戶使用,大大提升了GBDT模型在大樣本數據集上的訓練速度,使得用戶可以輕松地將GBDT模型用于樣本數10000個以上的數據集的訓練。而完整的LightGBM算法過于復雜,導致其參數、屬性、方法等有很多,故本書不再進行贅述,讀者可以移步LightGBM的官方文檔進行詳細了解,下面僅列舉出LightGBM中的常用參數,以及每個參數的所對應的調參場景。
7.3.1 常用參數
| max_depth | 基決策樹樹的最大深度 | 當模型過擬合時,可以考慮降低 max_depth的值以限制最大深度 |
| min_data_in_leaf | 基決策樹葉子節點所需要的最小樣本數 | 默認值為20,模型過擬合時用 |
| feature_fraction | 使用bagging方法時特征子集的采樣比例 | 指定boosting 方法為 random forest 時使用 |
| bagging_fractions | 使用bagging方法時樣本的采樣比例 | 用于加快訓練速度,減小過擬合的風險 |
| early_stopping_round | 指定使用提前停止方法的迭代次數上限。如果在一次驗證中模型對數據集的度量(如驗證錯誤率、驗證準確率等)在early_stopping_round輪迭代中中沒有得到提高,模型將終止訓練 | 減少因迭代次數過多造成計算資源的浪費 |
| lambda | 指定正則化系數 | 指定為0~1之間的實數,緩解過擬合 |
| min_gain_to_split | 指定基決策樹分裂時所要求的最小gain(信息增益) | 緩解過擬合 |
| Task | 模型對數據集的操作 | 指定為train表示對數據集進行擬合,指定為predict表示對數據進行預測 |
| application | 模型的用途 | 指定為regression表示完成回歸任務,指定為binary表示完成二分類任務, 指定為multiclass表示完成多分類任務 |
| num_boost_round | 迭代次數 | 通常設置成100以上 |
| learning_rate | 學習率 | 常用 0.1, 0.001等較小值 |
| num_leaves | 基決策樹節點數量 | 默認值為31(對應深度為5),取值應不大于 2max_depth2 ^{max\_depth}2max_depth, 超過此值會導致過擬合 |
| save_binary | 是否將數據集存儲為二進制文件 | 這個參數為 true 時,則數據集被保存為二進制文件,下次讀數據時速度會變快 |
| max_bin | 表示特征存入的最大bin數量 | 不得超過255 |
| device | 訓練模型所用的設備 | cpu | gpu |
| metric | 損失函數 |
7.3.2 常用調參方法
1 針對 Leaf-Wise策略
-
通過調整num_leaves參數來控制基決策樹中節點的數量,進而控制樹模型的復雜程度。一般情況下,若使用Level-Wise策略來生成基決策樹,則可以設置該參數的值為 2max_depth2^{max\_depth}2max_depth。但如果要使用Leaf_Wise策略來優化模型的擬合效果,則num_leaves 的取值應小于 2max_depth2^{max\_depth}2max_depth;
-
通過調整min_data_in_leaf參數來控制基決策樹中每個節點所要求的最小樣本數。該參數是處理Leaf-Wise 樹過擬合問題中一個非常重要的參數。將該值設置得較大可避免基決策樹的深度過深,,但設置得較大又有可能導致欠擬合,并且其取值不得超過訓練數據集的總樣本數 num_leaves。在實際應用中,應對該參數進行小心調整,調整的范圍一般在幾百到幾千之間;
-
通過調整max_depth參數顯式地限制基決策樹的的深度,以降低過擬合的風險。一般設置為5—10之間的整數。
2 針對更快的訓練速度
- 設置 bagging_fraction 和 bagging_freq 參數以使用 bagging 方法;
- 設置合適的feature_fraction 參數(表示特征子采樣的比例);
- 使用較小的 max_bin;
- 使用 save_binary ,用以在后續學習過程中加速對數據集的加載。
3 針對更好的準確率
-
使用較大的 max_bin (學習速度可能變慢);
-
使用較小的 learning_rate 和較大的 num_iterations;
-
使用較大的 num_leaves (可能導致過擬合);
-
使用更大的訓練數據集合。
4 緩解過擬合
-
使用較小的 max_bin(默認值為255);
-
使用較小的 num_leaves(默認為31);
-
調整 min_data_in_leaf(默認為20)和 min_sum_hessian_in_leaf(默認為e?3e^{-3}e?3)的值;
-
調整bagging_fraction (默認為1.0)和 bagging_freq (默認值為0,表示禁用bagging;將該值設置為kkk,表示每kkk次迭代執行一次bagging操作)的值以使用 bagging;
-
調整 feature_fraction(默認為1.0)的值以調整特征子采樣的比例;
-
使用更大的訓練數據;
-
使用 lambda_l1(默認為0), lambda_l2 (默認為0)和 min_split_gain(默認為0,表示執行切分的最小增益)以執行正則化操作;
-
嘗試調低 max_depth 的值,以避免生成過深的樹。
總結
以上是生活随笔為你收集整理的【集成学习系列教程5】LightGBM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深信服上网行为管理如何配置双因素/双因子
- 下一篇: python爬虫面试问题及答案_关于Py