天天看點

CatBoost, XGBoost, AdaBoost, LightBoost,各種Boost的介紹和對比

本篇文章内容

  1. 介紹
  2. AdaBoost
  3. Gradient Boost
    1. XGBoost
    2. Histogram-Based Gradient Boost
    3. LightBoost
    4. CatBoost
  4. 總結

介紹

在內建學習中,目标是用多種學習算法最成功地訓練模型。Bagging方法是一種內建學習方法,将多個模型并行應用于同一資料集的不同子樣本。Boosting是另一種在實踐中經常使用的方法,它不是并行建構的,而是按順序建構的,目的是訓練算法和模型。弱算法先對模型進行訓練,然後根據訓練結果對模型進行重組,使模型更容易學習。然後将修改後的模型發送給下一個算法,第二個算法比第一個算法學習起來更容易。本文包含了不同的增強方法,從不同的角度解釋了這些方法并進行了簡單的測試。

AdaBoost

自适應提升(Adaboost)是一種廣泛使用的基于決策樹樁(Decision stump: Threshold isassigned and the Prediction is made by the threshold.)的boosting方法。但是在Adaboost中并不是盲目地重複這種方法。建立了多個算法,這些算法依次更新它們的權值,并在做出最準确的估計時發揮各自的作用。計算了每種算法的錯誤率。權值被更新,是以被引用到第二種算法中。第二個算法對模型進行分類,像第一個模型一樣更新權重,并将其轉移到第三個算法。這些過程一直持續到n_estimator的數目或達到誤差=0。在這個過程中,由于權值由之前的算法更新并發送給其他算法,使得分類更加容易和成功。讓我們用一個例子來解釋這個複雜的順序算法過程:

假設有兩個标簽,紅色和藍色。第一種算法(弱分類器1)對标簽進行分離,結果是2個藍色樣本和1個紅色樣本被誤分類。這些錯誤分類的權重增加,正确分類的權重降低後,發送到下一個模型進行學習。在新模型中,錯誤分類樣本的偏差增大,而正确分類樣本的偏差減小,這兩種模型的學習效果較好。接下來的步驟将重複相同的過程。綜上所述,強分類是在弱分類的配合下發生的。因為它用于分類,是以也可以通過導入AdaBoostRegressor用于回歸。

超參數

base_estimators:一個順序改進的算法類(預設= DecisionTreeClassifier)

n_estimators:确定上述過程将采取的最大步驟數。(預設= 50)

learning_rate:決定權重的變化量。如果選擇過小,則n_estimators的值必須非常高。如果它被選得太大,它可能永遠達不到最優值。(預設= 1)

import numpy as np
 from time import time
 from sklearn.datasets import make_classification 
 from sklearn.model_selection import cross_val_score,train_test_split
 from sklearn.model_selection import KFold
 
 x,y = make_classification(n_samples=100000,n_features=30, n_informative=10, 
                           n_redundant=5,random_state=2021)           

複制

一個将用于所有方法的資料集已經導入,現在讓我們實作Adaboost:

from sklearn.ensemble import AdaBoostClassifier
 
 start_ada = time()
 ada = AdaBoostClassifier()
 
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 ada_score=cross_val_score(ada,x,y,cv=kf,n_jobs=-1)
 print("ada", np.round(time()-start_ada,5),"sec")
 print("acc", np.mean(ada_score).round(3))
 print("***************************")           

複制

Gradient Boost

Adaboost 通過使用決策樹樁(1 個節點分為 2 個葉子)更新權重來改進自身。梯度提升是另一種順序方法,通過建立 8 到 32 個葉子來優化損失,這意味着樹在梯度提升中更大(損失:就像是線上性模型中的殘差)。(y_test-y_prediction)通過每個資料點給出損失的平方和給出殘差。為什麼使用平方?因為我們正在尋找的值是預測與實際結果的偏差。負值平方後也會作用于損失值的計算 。簡而言之,将殘內插補點轉移到下一算法,使殘內插補點更接近于0,進而使損失值最小化。

GB = GradientBoostingClassifier()
 
 start_gb = time()
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 GB_score=cross_val_score(GB,x,y,cv=kf,n_jobs=-1)
 print("gb", np.round(time()-start_gb,5),"sec")
 print("acc", np.mean(GB_score).round(3))
 print("***************************")           

複制

在Adaboost中,梯度增強可以通過導入GradientBoostRegressor用于回歸。

from sklearn.metrics import mean_squared_error
 x_train, x_test, y_train, y_test = train_test_split(x, y,test_size=0.2,random_state=2021)
 gbr = GradientBoostingRegressor(max_depth=5, n_estimators=150)
 gbr.fit(x_train, y_train)
 error_list = [mean_squared_error(y_test, y_pred) for y_pred in gbr.staged_predict(x_test)]           

複制

OUT
 [0.22686585533221332,0.20713350861706786,0.1900682640534445,
  0.1761959477525979,0.16430532532798403,0.1540494010479854,
  0.14517117541343785,0.1375952312491854,0.130929810958826,
  0.12499605002264891,0.1193395594019215,0.11477096339545599,
  0.11067921343289967,0.10692446632551068,...................
  ...........................................................
  0.05488031632425609,0.05484366975329703,0.05480676108875857,
  0.054808073418709524,0.054740333154284,0.05460221966859833,
  0.05456647041868937,0.054489873127848434,0.054376259548495065,
  0.0542407250628274]           

複制

檢視Error_list,可以看到損失值在每一步都在變小。[從0.22開始,完成到0.05]

XGBoost

XGBoost(Extreme Gradient Boosting)是由Tianqi Chen在2014年開發的,在Gradient boost之前速度最快,是首選的Boosting方法。由于它包含超參數,可以進行許多調整,如正則化超參數防止過拟合。

超參數

booster [預設值=gbtree]決定那個使用那個booster,可以是gbtree,gblinear或者dart。gbtree和dart使用基于樹的模型,而gblinear 使用線性函數.

silent [預設值=0]設定為0列印運作資訊;設定為1靜默模式,不列印

nthread [預設值=設定為最大可能的線程數]并行運作xgboost的線程數,輸入的參數應該<=系統的CPU核心數,若是沒有設定算法會檢測将其設定為CPU的全部核心數下面的兩個參數不需要設定,使用預設的就好了

num_pbuffer [xgboost自動設定,不需要使用者設定]預測結果緩存大小,通常設定為訓練執行個體的個數。該緩存用于儲存最後boosting操作的預測結果。

num_feature [xgboost自動設定,不需要使用者設定]在boosting中使用特征的次元,設定為特征的最大次元

eta [預設值=0.3,别名:learning_rate]更新中減少的步長來防止過拟合。在每次boosting之後,可以直接獲得新的特征權值,這樣可以使得boosting更加魯棒。範圍:[0,1]

gamma [預設值=0,别名: min_split_loss](分裂最小loss)在節點分裂時,隻有分裂後損失函數的值下降了,才會分裂這個節點。Gamma指定了節點分裂所需的最小損失函數下降值。這個參數的值越大,算法越保守。這個參數的值和損失函數息息相關,是以是需要調整的。範圍: [0,∞]

max_depth [預設值=6]這個值為樹的最大深度。這個值也是用來避免過拟合的。max_depth越大,模型會學到更具體更局部的樣本。設定為0代表沒有限制範圍: [0,∞]

min_child_weight [預設值=1]決定最小葉子節點樣本權重和。XGBoost的這個參數是最小樣本權重的和,而GBM參數是最小樣本總數。這個參數用于避免過拟合。當它的值較大時,可以避免模型學習到局部的特殊樣本。但是如果這個值過高,會導緻欠拟合。這個參數需要使用CV來調整。.範圍: [0,∞]

subsample [預設值=1]這個參數控制對于每棵樹,随機采樣的比例。減小這個參數的值,算法會更加保守,避免過拟合。但是,如果這個值設定得過小,它可能會導緻欠拟合。典型值:0.5-1,0.5代表平均采樣,防止過拟合.範圍: (0,1]

colsample_bytree [預設值=1]用來控制每棵随機采樣的列數的占比(每一列是一個特征)。典型值:0.5-1範圍: (0,1]

colsample_bylevel [預設值=1]用來控制樹的每一級的每一次分裂,對列數的采樣的占比。我個人一般不太用這個參數,因為subsample參數

colsample_bytree參數可以起到相同的作用。但是如果感興趣,可以挖掘這個參數更多的用處。範圍: (0,1]

lambda [預設值=1,别名: reg_lambda]權重的L2正則化項。(和Ridge regression類似)。這個參數是用來控制XGBoost的正則化部分的。雖然大部分資料科學家很少用到這個參數,但是這個參數在減少過拟合上還是可以挖掘出更多用處的。.

alpha [預設值=0,别名: reg_alpha]權重的L1正則化項。(和Lasso regression類似)。可以應用在很高次元的情況下,使得算法的速度更快。

scale_pos_weight[預設值=1]在各類别樣本十分不平衡時,把這個參數設定為一個正值,可以使算法更快收斂。通常可以将其設定為負樣本的數目與正樣本數目的比值。

from xgboost import XGBClassifier
 
 xgb = XGBClassifier()
 
 start_xgb = time()
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 xgb_score=cross_val_score(xgb,x,y,cv=kf,n_jobs=-1)
 print("xgboost", np.round(time()-start_xgb,5))
 print("acc", np.mean(xgb_score).round(3))
 print("***************************")           

複制

Histogram-Based Gradient Boost

使用binning(discretizing)對資料進行分組,這是一種資料預處理方法,這裡已經解釋過了。例如,當給出“年齡”列時,将這些資料分為 30-40、40-50、50-60 3 組,然後将它們轉換為數值資料是一種非常有效的方法。當這種分箱方法适用于決策樹時,通過減少特征數量可以加快算法速度。該方法還可以通過将其與直方圖分組來用作建構每棵樹的內建。

from sklearn.experimental import enable_hist_gradient_boosting
 from sklearn.ensemble import HistGradientBoostingClassifier
 
 HGB = HistGradientBoostingClassifier()
 
 start_hgb = time()
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 HGB_score=cross_val_score(HGB,x,y,cv=kf,n_jobs=-1)
 print("hist", np.round(time()-start_hgb,5),"sec")
 print("acc", np.mean(HGB_score).round(3))
 print("***************************")           

複制

LightBoost

LGBM (Light Gradient Boosting Machine)是微軟于2017年首次釋出的一種基于決策樹的梯度增強方法,是使用者首選的另一種梯度增強方法。與其他方法的關鍵差別在于它是基于葉子進行樹的分裂,即它可以通過關鍵點位檢測和停計算(其他提升算法是基于深度或基于級别的)。由于LGBM是基于葉的,如圖2所示,LGBM是一種非常有效的方法,可以減少誤差,進而提高精度和速度。但是它不支援字元串類型的資料,需要使用特殊算法拆分分類資料,因為必須輸入整數值(例如索引)而不是列的字元串名稱。

CatBoost, XGBoost, AdaBoost, LightBoost,各種Boost的介紹和對比
from lightgbm import LGBMClassifier
 
 lgbm = LGBMClassifier()
 
 start_lgbm = time()
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 lgbm_score=cross_val_score(lgbm,x,y,cv=kf,n_jobs=-1)
 print("lgbm", np.round(time()-start_lgbm,5))
 print("acc", np.mean(lgbm_score).round(3))
 print("***************************")           

複制

CatBoost

CatBoost 由 Yandex 于 2017 年開發。由于它使用 One-Hot-Encoding 将所有分類特征轉換為數值,是以名稱來自 Categorical Boosting。将字元串自動轉化成索引值輸入的同屬他還處理了缺失的數值。而且它也比 XGBoost 快得多。與其他 boosting 方法不同,Catboost 與對稱樹進行區分,對稱樹在每個級别的節點中使用相同的拆分。

XGBoost 和 LGBM 計算每個資料點的殘差并訓練模型以獲得殘差目标值。它針對疊代次數重複此操作,進而訓練并降低殘差,進而達到目标。由于這種方法适用于每個資料點,是以在泛化方面可能會很弱并導緻過度拟合。

Catboost 還計算每個資料點的殘差,并使用其他資料訓練的模型進行計算。這樣,每個資料點就得到了不同的殘差資料。這些資料被評估為目标,并且通用模型的訓練次數與疊代次數一樣多。由于許多模型将根據定義實作,是以這種計算複雜性看起來非常昂貴并且需要太多時間。但是catboost通過有序提升但可以在更短的時間内完成。例如,catboost不是從每個資料點 (n+1)th 計算的殘差的開頭開始,俄日是計算(n+2)個資料點,應用(n+1)個資料點,依此類推

超參數

l2_leaf_reg:損失函數的L2正則化項。

learning_rate:學習率。在過度拟合的情況下降低 learning_rate。

depth:樹的深度,多在6-10之間使用。

one_hot_max_size:使用一個獨熱編碼對所有分類特征進行編碼,其中幾個不同的值小于或等于給定的參數值

grow_policy:決定樹的構造類型。可以使用 SymmetricTree、Depthwise 或 Lossguide。

from catboost import CatBoostClassifier
 
 cat = CatBoostClassifier()
 
 start_cat = time()
 kf=KFold(n_splits=5,shuffle=True,random_state=2021)
 cat_score=cross_val_score(cat,x,y,cv=kf,n_jobs=-1)
 print("cat", np.round(time()-start_cat,5))
 print("acc", np.mean(cat_score).round(3))
 print("***************************")           

複制

總結

在本文中,使用 DecisionTree 來處理提升方法,但可以通過更改相關的超參數輕松實作其他機器學習模型。此外,所有boosting方法都使用base version(未調整任何超參數)來比較boosting方法的性能,上面應用的代碼如下表:

CatBoost, XGBoost, AdaBoost, LightBoost,各種Boost的介紹和對比

作者:Ibrahim Kovan