XBG和LGB和CATBOOST 要用哪一種? 深度分析

概述

儘管最近幾年神經網絡復興,並變得流行起來,但我還是更加關注 boosting 算法,因爲在訓練樣本量有限、所需訓練時間較短、缺乏調參知識的場景中,它們依然擁有絕對優勢。

在這裏插入圖片描述

  • 2014 年 3 月,XGBOOST 最早作爲研究項目,由陳天奇提出

  • 2017 年 1 月,微軟發佈首個穩定版 LightGBM

  • 2017 年 4 月,俄羅斯頂尖技術公司 Yandex 開源 CatBoost

LightGBM 和 XGBoost 的結構差異

在過濾數據樣例尋找分割值時,LightGBM 使用的是全新的技術:基於梯度的單邊採樣(GOSS);而 XGBoost 則通過預分類算法和直方圖算法來確定最優分割。這裏的樣例(instance)表示觀測值/樣本。

首先讓我們理解預分類算法如何工作:

  • 對於每個節點,遍歷所有特徵

  • 對於每個特徵,根據特徵值分類樣例

  • 進行線性掃描,根據當前特徵的基本信息增益,確定最優分割

  • 選取所有特徵分割結果中最好的一個

簡單說,直方圖算法在某個特徵上將所有數據點劃分到離散區域,並通過使用這些離散區域來確定直方圖的分割值。雖然在計算速度上,和需要在預分類特徵值上遍歷所有可能的分割點的預分類算法相比,直方圖算法的效率更高,但和 GOSS 算法相比,其速度仍然更慢。
關鍵信息:預分類,直方圖算法,GOSS

爲什麼 GOSS 方法如此高效?

在 Adaboost 中,樣本權重是展示樣本重要性的很好的指標。但在梯度提升決策樹(GBDT)中,並沒有天然的樣本權重,因此 Adaboost 所使用的採樣方法在這裏就不能直接使用了,這時我們就需要基於梯度的採樣方法。

梯度表徵損失函數切線的傾斜程度,所以自然推理到,如果在某些意義上數據點的梯度非常大,那麼這些樣本對於求解最優分割點而言就非常重要,因爲算其損失更高。

GOSS 保留所有的大梯度樣例,並在小梯度樣例上採取隨機抽樣。比如,假如有 50 萬行數據,其中 1 萬行數據的梯度較大,那麼我的算法就會選擇(這 1 萬行梯度很大的數據+x% 從剩餘 49 萬行中隨機抽取的結果)。如果 x 取 10%,那麼最後選取的結果就是通過確定分割值得到的,從 50 萬行中抽取的 5.9 萬行。

在這裏有一個基本假設:如果訓練集中的訓練樣例梯度很小,那麼算法在這個訓練集上的訓練誤差就會很小,因爲訓練已經完成了。

爲了使用相同的數據分佈,在計算信息增益時,GOSS 在小梯度數據樣例上引入一個常數因子。因此,GOSS 在減少數據樣例數量與保持已學習決策樹的準確度之間取得了很好的平衡。
在這裏插入圖片描述

每個模型是如何處理分類變量的

CatBoost

完整版代碼 catboost(記不住的可以收藏)
關鍵詞:獨熱最大量,CatBoost

CatBoost 可賦予分類變量指標,進而通過獨熱最大量得到獨熱編碼形式的結果(獨熱最大量:在所有特徵上,對小於等於某個給定參數值的不同的數使用獨熱編碼)。

如果在 CatBoost 語句中沒有設置「跳過」,CatBoost 就會將所有列當作數值變量處理。

注意,如果某一列數據中包含字符串值,CatBoost 算法就會拋出錯誤。另外,帶有默認值的 int 型變量也會默認被當成數值數據處理。在 CatBoost 中,必須對變量進行聲明,纔可以讓算法將其作爲分類變量處理。

from catboost import CatBoostRegressor
cat_features = [0,1,2]
train_data = [["a","b",1,4,5,6],["a","b",4,5,6,7],["c","d",30,40,50,60]]
test_data = [["a","b",2,4,6,8],["a","b",1,4,50,60]]
train_labels = [10,20,30]
model = CatBoostRegressor(iterations=2,learning_rate=1,depth=2)
model.fit(train_data,train_labels,cat_features)

這裏面的cat_features表示,第一個特徵需要編碼,這裏是0,1,2個特徵都要編碼,就是兩個字符特徵和第一個整數特徵都是按照分類變量來看待的。這裏也可以是[0,1]。
對於可取值的數量比獨熱最大量還要大的分類變量,CatBoost 使用了一個非常有效的編碼方法,這種方法和均值編碼類似,但可以降低過擬合情況。它的具體實現方法如下:

  1. 將輸入樣本集隨機排序,並生成多組隨機排列的情況。

  2. 將浮點型或屬性值標記轉化爲整數。

  3. 將所有的分類特徵值結果都根據以下公式,轉化爲數值結果。

在這裏插入圖片描述

其中 CountInClass 表示在當前分類特徵值中,有多少樣本的標記值是「1」;Prior 是分子的初始值,根據初始參數確定。TotalCount 是在所有樣本中(包含當前樣本),和當前樣本具有相同的分類特徵值的樣本數量。

LightBGM

和 CatBoost 類似,LighGBM 也可以通過使用特徵名稱的輸入來處理屬性數據;它沒有對數據進行獨熱編碼,因此速度比獨熱編碼快得多。LGBM 使用了一個特殊的算法來確定屬性特徵的分割值。
在這裏插入圖片描述

注意,在建立適用於 LGBM 的數據集之前,需要將分類變量轉化爲整型變量;此算法不允許將字符串數據傳給分類變量參數。

XGBoost

和 CatBoost 以及 LGBM 算法不同,XGBoost 本身無法處理分類變量,而是像隨機森林一樣,只接受數值數據。因此在將分類數據傳入 XGBoost 之前,必須通過各種編碼方式:例如標記編碼、均值編碼或獨熱編碼對數據進行處理。

超參數中的相似性

在這裏插入圖片描述

結果對比

在一次預測任務中,我對比了結果,下面是結果分析:

爲了評估模型,我們應該同時考慮模型的速度和準確度表現。

請記住,CatBoost 在測試集上表現得最好,測試集的準確度最高(0.816)、過擬合程度最小(在訓練集和測試集上的準確度很接近)以及最小的預測和調試時間。但這個表現僅僅在有分類特徵,而且調節了獨熱最大量時纔會出現。如果不利用 CatBoost 算法在這些特徵上的優勢,它的表現效果就會變成最差的:僅有 0.752 的準確度。因此我們認爲,只有在數據中包含分類變量,同時我們適當地調節了這些變量時,CatBoost 纔會表現很好。

第二個使用的是 XGBoost,它的表現也相當不錯。即使不考慮數據集包含有轉換成數值變量之後能使用的分類變量,它的準確率也和 CatBoost 非常接近了。但是,XGBoost 唯一的問題是:它太慢了。尤其是對它進行調參,非常令人崩潰(我用了 6 個小時來運行 GridSearchCV——太糟糕了)。更好的選擇是分別調參,而不是使用 GridSearchCV。

最後一個模型是 LightGBM,這裏需要注意的一點是,在使用 CatBoost 特徵時,LightGBM 在訓練速度和準確度上的表現都非常差。我認爲這是因爲它在分類數據中使用了一些修正的均值編碼方法,進而導致了過擬合(訓練集準確率非常高:0.999,尤其是和測試集準確率相比之下)。但如果我們像使用 XGBoost 一樣正常使用 LightGBM,它會比 XGBoost 更快地獲得相似的準確度,如果不是更高的話(LGBM—0.785, XGBoost—0.789)。

最後必須指出,這些結論在這個特定的數據集下成立,在其他數據集中,它們可能正確,也可能並不正確。但在大多數情況下,XGBoost 都比另外兩個算法慢。

總結:CatBoost自帶的編碼效果非常好,在處理有分類特徵的預測任務的時候,效果好;XGB效果跟LGM相差無幾但是速度太慢,需要自己事先對分類變量進行編碼;LGM自帶的編碼效果不佳,但是如果按照XGB的事先進行編碼,則效果會強於XGB

個人認爲,XGB也許可以被LGB代替,CatBoost感覺會跟LGB重要性相當。

發佈了76 篇原創文章 · 獲贊 8 · 訪問量 7384
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章