學習器html
參數node
oob_score=True
來經過包外估計來估計模型的泛化偏差(也就不須要進行交叉驗證了)Note:方差的產生主要是不一樣的樣本訓練獲得的學習器對於同一組測試集作出分類、預測結果的波動性,究其緣由是基學習器可能學到了所供學習的訓練樣本中的局部特徵或者說是擬合了部分噪聲數據,這樣綜合不一樣的學習器的結果,採起多數表決(分類)或者平均(迴歸)的方法能夠有效改善這一情況python
學習器git
Notes:web
隨機森林的行採樣(bagging)和列採樣(feature bagging)都是爲了減少模型之間的相關性使基學習器變得不一樣從而減少集成模型的方差算法
Extra-Trees(extremely randomized trees):相較於rf進一步加強了隨機性,rf是對各個基學習器隨機挑選了部分特徵來作維特徵子集從中挑選最佳的特徵切分,而Extra-Trees更進一步,在特徵子集裏挑選最佳特徵時不是選擇最有區分度的特徵值,而是隨機選擇這一劃分的閾值(該閾值在子特徵集裏的特徵對應的採樣後的樣本取值範圍裏隨機選取),而不一樣的隨機閾值下的特徵中表現最佳的做爲劃分特徵,這樣其實加強了隨機性,更進一步整大了基學習器的誤差但下降了總體的方差bootstrap
調參緩存
方法安全
特徵選擇性能優化
特徵重要性評估:一棵樹中的特徵的排序(好比深度)能夠用來做爲特徵相對重要性的一個評估,居於樹頂端的特徵相對而言對於最終樣本的劃分貢獻最大(通過該特徵劃分所涉及的樣本比重最大),這樣能夠經過對比各個特徵所劃分的樣本比重的一個指望值來評估特徵的相對重要性,而在隨機森林中,經過對於不一樣樹的特徵的指望取一個平都可以減少評估結果的方差,以供特徵選擇;在sklearn中這些評估最後被保存在訓練好的模型的參數featureimportances裏,是各個特徵的重要性值通過歸一化的結果,越高表明特徵越匹配預測函數
Notes:
隨機森林與KNN
_Notes:調參的關鍵參數是基學習器的數量n_estimators
以及基學習器自己的複雜性好比深度max_depth
或者葉節點所需的最少樣本數min_samples_leaf
_
概述
Gradient Tree Boosting或者說GBRT是boosting的一種推廣,是的能夠應用通常的損失函數,能夠處理分類問題和迴歸問題,應用普遍,常見應用場景好比網頁搜索排序和社會生態學
優缺點
學習器
GradientBoostingClassifier
n_estimators
max_depth
或者葉節點數目max_leaf_nodes
來控制(注意兩種樹的生長方式不一樣,max_leaf_nodes
是針對葉節點優先挑選不純度降低最多的葉節點,這裏有點LightGBM的’leaf-wise’的意味,而按樹深分裂則更相似於原始的以及XGBoost的分裂方式)learning_rate
對應取值範圍在(0,1]之間的超參數對應GBRT裏的shrinkage來避免過擬合(是sklearn裏的GBDT用來進行正則化的一種策略);n_classes
對應每輪迭代的迴歸樹,這樣整體樹的數目是n_classes*n_estimators
criterion
用來設置迴歸樹的切分策略
friedman_mse
,對應的最小平方偏差的近似,加入了Friedman的一些改進mse
對應最小平方偏差mae
對應平均絕對值偏差subsample
:行採樣,對樣本採樣,即訓練每一個基學習器時再也不使用原始的所有數據集,而是使用一部分,而且使用隨機梯度上升法來作集成模型的訓練max_features
在訓練基學習器時使用一個特徵子集來訓練,相似隨機森林的作法min_impurity_split
(原始)以及min_impurity_decrease
來實現,前者的是根據節點的不純度是否高於閾值,若不是則中止增加樹,做爲葉節點;後者則根據分裂不純度降低值是否超過某一閾值來決定是否分裂(此外這裏的early stopping彷佛與XGBoost裏顯示設置的early stopping不一樣,這裏是控制樹的切分生長,而XGBoost則是控制基學習器的數目)init
,用來計算初始基學習器的預測,須要具有fit
和predict
方法,若未設置則默認爲loss.init_estimator
warm_start
,若設置爲True則能夠使用已經訓練好的學習器,而且在其上添加更多的基學習器presort
,默認設置爲自動,對樣本按特徵值進行預排序從而提升尋找最優切分點的效率,自動模式下對稠密數據會使用預排序,而對稀疏數據則不會loss
)
n_classes
互斥的多分類,提供機率估計,初始模型值設爲各種別的先驗機率,每一輪迭代須要構建n類迴歸樹可能會使得模型對於多類別的大數據集不過高效feature_importances_
):進行特徵重要性的評估oob_improvement_
),使用包外樣原本計算每一輪訓練後模型的表現提高train_score_
)estimators_
)fit
方法裏能夠設置樣本權重sample_weight
,monitor
能夠用來回調一些方法好比包外估計、早中止等GradientBoostingRegressor
ls
train_score_
可得到每輪訓練的訓練偏差,經過方法staged_predict
能夠得到每一階段的測試偏差,經過屬性feature_importances_
能夠輸出模型判斷的特徵相對重要性正則化
learning rate
一種簡單的正則化的策略,經過控制每個基學習器的貢獻,會影響到基學習器的數目即n_estimators
,經驗性的設置爲一個較小的值,好比不超過0.1的常數值,而後使用early stopping來控制基學習器的數目subsample
),通常設置shrinkage比不設置要好,而加上行採樣會進一步提高效果,而僅使用行採樣可能效果反而不佳;並且進行行採樣後可以使用包外估計來計算模型每一輪訓練的效果提高,保存在屬性oob_improvement_
裏,能夠用來作模型選擇,可是包外預估的結果一般比較悲觀,因此除非交叉驗證太過耗時,不然建議結合交叉驗證一塊兒進行模型選擇max_features
來實現可解釋性
單一的決策樹能夠經過將樹結構可視化來分析和解釋,而梯度上升模型由於由上百課迴歸樹組成所以他們很難像單獨的決策樹同樣被可視化,不過也有一些技術來輔助解釋模型
Notes:
Voting的基本思想是將不一樣學習器的結果進行硬投票(多數表決)或者軟投票(對預測機率加權平均)來對樣本類別作出預估,其目的是用來平衡一些表現至關且都還不錯的學習器的表現,以消除它們各自的缺陷
voting
=’hard’):按照多數表決原則,根據分類結果中多數預測結果做爲輸入樣本的預測類別,若是出現類別數目相同的狀況,會按照預測類別的升序排序取前一個預測類別(好比模型一預測爲類別‘2’,模型二預測爲類別‘1’則樣本會被判爲類別1)wights
爲一個列表表示各個基學習器的權重值XGBoost裏能夠使用兩種方式防止過擬合
max_depth
,基學習器的深度,增長該值會使基學習器變得更加複雜,榮易過擬合,設爲0表示不設限制,對於depth-wise的基學習器學習方法須要控制深度min_child_weight
,子節點所需的樣本權重和(hessian)的最小閾值,如果基學習器切分後獲得的葉節點中樣本權重和低於該閾值則不會進一步切分,在線性模型中該值就對應每一個節點的最小樣本數,該值越大模型的學習約保守,一樣用於防止模型過擬合gamma
,葉節點進一步切分的最小損失降低的閾值(超過該值才進一步切分),越大則模型學習越保守,用來控制基學習器的複雜度(有點LightGBM裏的leaf-wise切分的意味)subsample
colsample_bytree
eta
即shrinkage對於XGBoost來講一樣是兩種方式
scale_pos_weight
max_delta_step
爲一個有限值好比1來加速模型訓練的收斂主要用於設置基學習器的類型
booster
nthread
,設置並行的線程數,默認是最大線程數在基學習器肯定後,根據基學習器來設置的一些個性化的參數
eta
,步長、學習率,每一輪boosting訓練後能夠獲得新特徵的權重,能夠經過eta來適量縮小權重,使模型的學習過程更加保守一點,以防止過擬合gamma
,葉節點進一步切分的最小損失降低的閾值(超過該值才進一步切分),越大則模型學習越保守,用來控制基學習器的複雜度(有點LightGBM裏的leaf-wise切分的意味)max_depth
,基學習器的深度,增長該值會使基學習器變得更加複雜,榮易過擬合,設爲0表示不設限制,對於depth-wise的基學習器學習方法須要控制深度min_child_weight
,子節點所需的樣本權重和(hessian)的最小閾值,如果基學習器切分後獲得的葉節點中樣本權重和低於該閾值則不會進一步切分,在線性模型中該值就對應每一個節點的最小樣本數,該值越大模型的學習約保守,一樣用於防止模型過擬合max_delta_step
,樹的權重的最大估計值,設爲0則表示不設限,設爲整數會是模型學習相對保守,通常該參數沒必要設置,可是對於基學習器是LR時,在針對樣本分佈極爲不均的狀況控制其值在1~10之間能夠控制模型的更新subsample
,基學習器使用樣本的比重colsample_bytree
,用於每棵樹劃分的特徵比重colsample_bylevel
,用於每層劃分的特徵比重alpha
lambda
tree_method
,樹的構建方法,準確的說應該是切分點的選擇算法,包括原始的貪心、近似貪心、直方圖算法(可見LightGBM這裏並非一個區別)
auto
,啓發式地選擇分割方法,近似貪心或者貪心exact
,原始的貪心算法,既針對每個特徵值切分一次approx
,近似的貪心算法選取某些分位點進行切分,使用sketching和histogramhist
,直方圖優化的貪心算法,對應的參數有grow_policy
,max_bin
gpu_exact
gpu_hist
scale_pos_weight
,針對數據集類別分佈不均,典型的值可設置爲 sum(negativecases)sum(positivecases)sum(negativecases)sum(positivecases)
grow_policy
,控制樹的生長方式,目前只有當樹的構建方法tree_method
設置爲hist
時才能夠使用所謂的leaf-wise
生長方式
depthwise
,按照離根節點最近的節點進行分裂lossguide
,優先分裂損失變化大的節點,對應的一個參數還有max_leaves
,表示可增長的最大的節點數max_bin
,一樣針對直方圖算法tree_method
設置爲hist
時用來控制將連續特徵離散化爲多個直方圖的直方圖數目predictor
,選擇使用GPU或者CPU
cpu_predictor
gpu_predictor
根據任務、目的設置的參數,好比迴歸任務與排序任務的目的是不一樣的
reg:linear
,線性迴歸reg:logistic
,邏輯迴歸binary:logistic
,使用LR二分類,輸出機率binary:logitraw
,使用LR二分類,但在進行logistic轉換以前直接輸出分類得分count:poisson
,泊松迴歸multi:softmax
,使用softmax進行多分類,須要設置類別數num_class
multi:softprob
rank:pairwise
,進行排序任務,最小化pairwise損失reg:gamma
,gamma迴歸reg:tweedie
,tweedie迴歸eval_metric
,默認根據目標函數設置,針對驗證集,默認狀況下,最小均方偏差用於迴歸,錯分用於分類,平均精確率用於排序等,能夠同時使用多個評估指標,在python裏使用列表來放置
rmse
mae
logloss
,負的對數似然error
,根據0.5做爲閾值判斷的錯分率error@t
merror
mlogloss
auc
主要用來排序ndcg
,normalized discounted cumulative gain及其餘的一些針對泊松迴歸等問題的評價指標num_round
迭代次數,也對應基學習器數目task
當前對模型的任務,包括
train
pred
eval
dump
model_in
和model_out
fmap
,feature map用來導出模型直方圖算法,LightGBM提供一種數據類型的封裝相對Numpy,Pandas,Array等數據對象而言節省了內存的使用,緣由在於他只須要保存離散的直方圖,LightGBM裏默認的訓練決策樹時使用直方圖算法,XGBoost裏如今也提供了這一選項,不過默認的方法是對特徵預排序,直方圖算法是一種犧牲了必定的切分準確性而換取訓練速度以及節省內存空間消耗的算法
對稀疏特徵構建直方圖時的時間複雜度爲O(2*#非零數據)
LEAF-WISE(BEST-FIRST)樹生長策略
相對於level-wise的生長策略而言,這種策略每次都是選取當前損失降低最多的葉節點進行分割使得總體模型的損失降低得更多,可是容易過擬合(特別當數據量較小的時候),能夠經過設置參數max_depth
來控制樹身防止出現過擬合
Notes:XGBoost如今兩種方式都是支持的
直接支持類別特徵
對於類別類型特徵咱們原始的作法是進行獨熱編碼,可是這種作法對於基於樹的模型而言不是很好,對於基數較大的類別特徵,可能會生成很是不平衡的樹而且須要一顆很深的樹才能達到較好的準確率;比較好的作法是將類別特徵劃分爲兩個子集,直接劃分方法衆多(2^(k-1)-1),對於迴歸樹而言有一種較高效的方法只須要O(klogk)的時間複雜度,基本思想是對類別按照與目標標籤的相關性進行重排序,具體一點是對於保存了類別特徵的直方圖根據其累計值(sum_gradient/sum_hessian)重排序,在排序好的直方圖上選取最佳切分位置
使用collective communication算法替代了point-to-point communication算法提高了效率
特徵並行
特徵並行是爲了將尋找決策樹的最佳切分點這一過程並行化
Notes:典型的空間換時間,差異就是減小了傳輸切分結果的步驟,節省了這裏的通訊消耗
數據並行
上述特徵並行的方法並無根本解決尋找切分點的計算效率問題,當記錄數過大時須要考慮數據並行的方法
並行投票
進一步減少了數據並行中的通訊代價,經過兩輪的投票來減少特徵直方圖中的通訊消耗
直接支持類別(標稱)特徵
LightGBM能夠直接用類別特徵進行訓練,沒必要預先進行獨熱編碼,速度會提高很多,參數設置categorical_feature
來指定數據中的類別特徵列
早中止
sklearn-GBDT,XGBoost,LightGBM都支持早中止,不過在細節上略有不一樣
min_impurity_split
(原始)以及min_impurity_decrease
來實現,前者的是根據節點的不純度是否高於閾值,若不是則中止增加樹,做爲葉節點;後者則根據分裂不純度降低值是否超過某一閾值來決定是否分裂(此外這裏的early stopping彷佛與XGBoost裏顯示設置的early stopping不一樣,這裏是控制樹的切分生長,而XGBoost則是控制基學習器的數目)bst.best_score, bst.best_iteration, bst.best_ntree_limit
,官方的建議是在作預測時設置爲bst.best_ntree_limit
,實際使用時感受bst.best_iteration
和 bst.best_ntree_limit
的表現上區別不大bst.best_iteration
這一種方式實踐上
支持的任務
支持的評價指標METRIC
l1
l2
l2_root
binary_logloss
,multi_logloss
binary_error
,multi_error
num_leaves
,與模型複雜度直接相關(leaf-wise)regression
,對應的損失函數以下
regression_l1
,加了l1正則的迴歸,等同於絕對值偏差regression_l2
,等同於均方偏差huber
,Huber Lossfair
,Fair Losspoisson
,泊松迴歸binary
,二分類multiclass
,多分類lambdarank
boosting
gbdt
,傳統的梯度提高決策樹rf
,隨機森林dart
,Dropouts meet Multiple Additive Regression Treesgoss
,Gradient-based One-Side Samplingnum_iterations
,對於多分類問題,LightGBM會構建num_class*num_iterations的樹learning_rate
,即shrinkagetree_learner
,主要用來控制樹是否並行化訓練
serial
,單機的樹學習器feature
,特徵並行的樹學習器data
,數據並行的樹學習器num_threads
device
,使用cpu仍是gpu
cpu
gpu
防止過擬合
max_depth
,主要用來避免模型的過擬合,設爲負數值則代表不限制min_data_in_leaf
min_sum_hessian_in_leaf
feature_fraction
,每棵樹的特徵子集佔比,設置在0~1之間,能夠加快訓練速度,避免過擬合bagging_fraction
,不進行重採樣的隨機選取部分樣本數據,此外須要設置參數bagging_freq
來做爲採樣的頻率,即多少輪迭代作一次bagging;early_stopping_roung
,在某一驗證數據的某一驗證指標當前最後一輪迭代沒有提高時中止迭代lambda_l1
lambda_l2
min_gain_to_split
直方圖相關
max_bin
,特徵值裝載的最大直方圖數目,通常較小的直方圖數目會下降訓練的準確性但會提高總體的表現,處理過擬合min_data_in_bin
,設置每一個直方圖中樣本數的最小值,一樣防止過擬合特徵相關
is_pre_partition
is_sparse
categorical_feature
,聲明類別特徵對應的列(經過索引標記),僅支持int類型weight
,指定一列做爲權重列內存相關
two_round
,通常LightGBM將數據載入內存進行處理,這樣會提高數據的加載速度,可是對於數據量較大時會形成內存溢出,因此此時須要分階段載入save_binary
,將數據文件導出爲二進制文件,下次加載數據時就會更快一些缺失值
use_missing
zeros_as_missing
sigmoid
,sigmoid函數中的參數,用於二分類和排序任務scale_pos_weight
,設置正例在二分類任務中的樣本佔比boost_from_average
,調整初始的分數爲標籤的均值,加速模型訓練的收斂速度,僅用於迴歸任務is_unbalance
num_class
,用於多分類LEAF-WISE
num_leaves
,對於leaf-wise的模型而言該參數是用來控制模型複雜度的主要參數,理論上能夠經過設置num_leaves
=2^(max_depth)來設置該參數值,實際是不可取的,由於在節點數目相同的前提下,對於leaf-wise的模型會傾向於生成深度更深的模型,若是生硬的設置爲2^(max_depth)可能會形成模型的過擬合,通常設置的值小於2^(max_depth),min_data_in_leaf
,在設置了葉節點數後,該值會對模型複雜度形成影響,若設的較大則樹不會生長的很深,但可能形成模型的欠擬合max_depth
效率
bagging_fraction
和bagging_freq
,使用bagging進行行採樣提高訓練速度(減少了數據集)feature_fraction
,列採樣max_bin
save_binary
準確率
max_bin
,固然這樣會犧牲訓練速度learning_rate
,這樣會增長迭代次數num_leaves
,可能形成模型過擬合dart
模型過擬合
max_bin
num_leaves
min_data_in_leaf
和min_sum__hessian_in_leaf
bagging_fraction
和bagging_freq
feature_fraction
,列採樣lambda_l1
lambda_l2
min_gain_to_split
max_depth
實際在庫的實現層面原始論文裏的不少區別是不存在的,差別更多在一些工程上的性能優化
min_impurity_split
即控制了判斷葉節點是否進一步切分的不純度的閾值,若超過該閾值則能夠進一步切分,不然不行,故而控制了樹的深度即控制了基學習器的複雜度XGBoost目前已經實現了LightGBM以前不一樣的一些方法好比直方圖算法,二者的區別更多的在與LightGBM優化通訊的的一些處理上
lightGBM與XGBoost的區別:
(1)xgboost採用的是level-wise的分裂策略,而lightGBM採用了leaf-wise的策略,區別是xgboost對每一層全部節點作無差異分裂,可能有些節點的增益很是小,對結果影響不大,可是xgboost也進行了分裂,帶來了務必要的開銷。 leaft-wise的作法是在當前全部葉子節點中選擇分裂收益最大的節點進行分裂,如此遞歸進行,很明顯leaf-wise這種作法容易過擬合,由於容易陷入比較高的深度中,所以須要對最大深度作限制,從而避免過擬合。
(2)lightgbm使用了基於histogram的決策樹算法,這一點不一樣與xgboost中的 exact 算法,histogram算法在內存和計算代價上都有不小優點。
-. 內存上優點:很明顯,直方圖算法的內存消耗爲(#data* #features * 1Bytes)(由於對特徵分桶後只需保存特徵離散化以後的值),而xgboost的exact算法內存消耗爲:(2 * #data * #features* 4Bytes),由於xgboost既要保存原始feature的值,也要保存這個值的順序索引,這些值須要32位的浮點數來保存。
-. 計算上的優點,預排序算法在選擇好分裂特徵計算分裂收益時須要遍歷全部樣本的特徵值,時間爲(#data),而直方圖算法只須要遍歷桶就好了,時間爲(#bin)
(3)直方圖作差加速
-. 一個子節點的直方圖能夠經過父節點的直方圖減去兄弟節點的直方圖獲得,從而加速計算。
(4)lightgbm支持直接輸入categorical 的feature
-. 在對離散特徵分裂時,每一個取值都看成一個桶,分裂時的增益算的是」是否屬於某個category「的gain。相似於one-hot編碼。
(5)但實際上xgboost的近似直方圖算法也相似於lightgbm這裏的直方圖算法,爲何xgboost的近似算法比lightgbm仍是慢不少呢?
-. xgboost在每一層都動態構建直方圖, 由於xgboost的直方圖算法不是針對某個特定的feature,而是全部feature共享一個直方圖(每一個樣本的權重是二階導),因此每一層都要從新構建直方圖,而lightgbm中對每一個特徵都有一個直方圖,因此構建一次直方圖就夠了。
-. lightgbm作了cache優化?
(6)lightgbm哪些方面作了並行?
-. feature parallel
通常的feature parallel就是對數據作垂直分割(partiion data vertically,就是對屬性分割),而後將分割後的數據分散到各個workder上,各個workers計算其擁有的數據的best splits point, 以後再彙總獲得全局最優分割點。可是lightgbm說這種方法通信開銷比較大,lightgbm的作法是每一個worker都擁有全部數據,再分割?(沒懂,既然每一個worker都有全部數據了,再彙總有什麼意義?這個並行體如今哪裏??)
-. data parallel
傳統的data parallel是將對數據集進行劃分,也叫 平行分割(partion data horizontally), 分散到各個workers上以後,workers對獲得的數據作直方圖,彙總各個workers的直方圖獲得全局的直方圖。 lightgbm也claim這個操做的通信開銷較大,lightgbm的作法是使用」Reduce Scatter「機制,不彙總全部直方圖,只彙總不一樣worker的不一樣feature的直方圖(原理?),在這個彙總的直方圖上作split,最後同步。
XGBoost(eXtreme Gradient Boosting)全名叫極端梯度提高
目錄
1. 最優模型的構建方法
2. Boosting的迴歸思想
3. XGBoost的目標函數推導
4. XGBoost的迴歸樹構建方法
5. XGBoost與GDBT的區別
最優模型的構建方法
構建最優模型的通常方法是最小化訓練數據的損失函數,咱們用字母 L表示,以下式:
式(1)稱爲經驗風險最小化,訓練獲得的模型複雜度較高。當訓練數據較小時,模型很容易出現過擬合問題。
所以,爲了下降模型的複雜度,常採用下式:
其中J(f)爲模型的複雜度,式(2)稱爲結構風險最小化,結構風險最小化的模型每每對訓練數據以及未知的測試數據都有較好的預測 。
應用:決策樹的生成和剪枝分別對應了經驗風險最小化和結構風險最小化,XGBoost的決策樹生成是結構風險最小化的結果
Boosting方法的迴歸思想
Boosting法是結合多個弱學習器給出最終的學習結果,無論任務是分類或迴歸,咱們都用迴歸任務的思想來構建最優Boosting模型 。
迴歸思想:把每一個弱學習器的輸出結果當成連續值,這樣作的目的是能夠對每一個弱學習器的結果進行累加處理,且能更好的利用損失函數來優化模型。
假設是第 t 輪弱學習器的輸出結果,
是模型的輸出結果,
是實際輸出結果,表達式以下:
上面兩式就是加法模型,都默認弱學習器的輸出結果是連續值。由於迴歸任務的弱學習器自己是連續值,因此不作討論,下面詳細介紹分類任務的迴歸思想。
分類任務的迴歸思想:
根據2.1式的結果,獲得最終的分類器:
分類的損失函數通常選擇指數函數或對數函數,這裏假設損失函數爲對數函數,學習器的損失函數是
若實際輸出結果yi=1,則:
求(2.5)式對的梯度,得:
負梯度方向是損失函數降低最快的方向,(2.6)式取反的值大於0,所以弱學習器是往增大的方向迭代的,圖形表示爲:
如上圖,當樣本的實際標記 yi 是 1 時,模型輸出結果隨着迭代次數的增長而增長(紅線箭頭),模型的損失函數相應的減少;當樣本的實際標記 yi 是 -1時,模型輸出結果
隨着迭代次數的增長而減少(紅線箭頭),模型的損失函數相應的減少 。這就是加法模型的原理所在,經過屢次的迭代達到減少損失函數的目的。
小結:Boosting方法把每一個弱學習器的輸出當作是連續值,使得損失函數是個連續值,所以能夠經過弱學習器的迭代達到優化模型的目的,這也是集成學習法加法模型的原理所在 。
XGBoost算法的目標函數推導
目標函數,即損失函數,經過最小化損失函數來構建最優模型,由第一節可知, 損失函數應加上表示模型複雜度的正則項,且XGBoost對應的模型包含了多個CART樹,所以,模型的目標函數爲:
(3.1)式是正則化的損失函數,等式右邊第一部分是模型的訓練偏差,第二部分是正則化項,這裏的正則化項是K棵樹的正則化項相加而來的。
CART樹的介紹:
上圖爲第K棵CART樹,肯定一棵CART樹須要肯定兩部分,第一部分就是樹的結構,這個結構將輸入樣本映射到一個肯定的葉子節點上,記爲。第二部分就是各個葉子節點的值,q(x)表示輸出的葉子節點序號,
表示對應葉子節點序號的值。由定義得:
樹的複雜度定義
XGBoost法對應的模型包含了多棵cart樹,定義每棵樹的複雜度:
其中T爲葉子節點的個數,||w||爲葉子節點向量的模 。γ表示節點切分的難度,λ表示L2正則化係數。
以下例樹的複雜度表示:
目標函數推導
根據(3.1)式,共進行t次迭代的學習模型的目標函數爲:
泰勒公式的二階導近似表示:
令爲Δx,則(3.5)式的二階近似展開:
其中:
表示前t-1棵樹組成的學習模型的預測偏差,gi和hi分別表示預測偏差對當前模型的一階導和二階導 ,當前模型往預測偏差減少的方向進行迭代。
忽略(3.8)式常數項,並結合(3.4)式,得:
經過(3.2)式簡化(3.9)式:
(3.10)式第一部分是對全部訓練樣本集進行累加,由於全部樣本都是映射爲樹的葉子節點,咱們換種思惟,從葉子節點出發,對全部的葉子節點進行累加,得:
令
Gj 表示映射爲葉子節點 j 的全部輸入樣本的一階導之和,同理,Hj表示二階導之和。
得:
對於第 t 棵CART樹的某一個肯定結構(可用q(x)表示),其葉子節點是相互獨立的,Gj和Hj是肯定量,所以,(3.12)能夠當作是關於葉子節點的一元二次函數 。最小化(3.12)式,得:
獲得最終的目標函數:
(3.14)也稱爲打分函數(scoring function),它是衡量樹結構好壞的標準,值越小,表明這樣的結構越好 。咱們用打分函數選擇最佳切分點,從而構建CART樹。
CART迴歸樹的構建方法
上節推導獲得的打分函數是衡量樹結構好壞的標準,所以,可用打分函數來選擇最佳切分點。首先肯定樣本特徵的全部切分點,對每個肯定的切分點進行切分,切分好壞的標準以下:
Gain表示單節點obj*與切分後的兩個節點的樹obj*之差,遍歷全部特徵的切分點,找到最大Gain的切分點便是最佳分裂點,根據這種方法繼續切分節點,獲得CART樹。若 γ 值設置的過大,則Gain爲負,表示不切分該節點,由於切分後的樹結構變差了。γ值越大,表示對切分後obj降低幅度要求越嚴,這個值能夠在XGBoost中設定。
XGBoost與GDBT的區別
1. XGBoost生成CART樹考慮了樹的複雜度,GDBT未考慮,GDBT在樹的剪枝步驟中考慮了樹的複雜度。
2. XGBoost是擬合上一輪損失函數的二階導展開,GDBT是擬合上一輪損失函數的一階導展開,所以,XGBoost的準確性更高,且知足相同的訓練效果,須要的迭代次數更少。
3. XGBoost與GDBT都是逐次迭代來提升模型性能,可是XGBoost在選取最佳切分點時能夠開啓多線程進行,大大提升了運行速度。
上文介紹了XGBoost的算法原理並引出了衡量樹結構好壞的打分函數(目標函數),根據特徵切分點先後的打分函數選擇最佳切分點,但並未對節點的切分算法做詳細的介紹。本文詳細的介紹了XGBoost的切分點算法
目錄
並行原理
切分點算法之貪婪算法
切分點算法之分位點算法
切分點算法之權重分位點算法
稀疏數據的切分算法
總結
1. 並行原理
XGBoost是串行生成CART樹,可是XGBoost在處理特徵時能夠作到並行處理,XGBoost並行原理體如今最優切分點的選擇,假設樣本數據共M個特徵,對於某一輪CART樹的構建過程當中,選擇最佳切分點算法以下圖:
1. 紅色框表示根據每一個特徵大小對訓練數據進行排序,保存爲block結構,block個數與特徵數量相等。
2. 綠色寬表示對每一個block結構選擇最佳特徵切分點 ,節點切分標準是目標函數降低的程。
3. 黑色框表示比較每一個block結構的最佳特徵切分點的目標函數降低的增益,選擇最佳切分點。
2. 切分點算法之貪婪算法
每個block結構的切分點算法思路是相同的,所以,我重點介紹某一塊block結構的切分點算法。
XGBoost分位點算法:根據特徵對樣本數據進行排序,而後特徵從小到大進行切分,比較每次切分後的目標函數大小,選擇降低最大的節點做爲該特徵的最優切分點。最後比較不一樣block塊結構最優切分點的目標函數降低值,選擇降低最大的特徵做爲最優切分點。
流程圖以下:
【例】下表表示樣本的某一列特徵數值
根據特徵大小對樣本從新排序:
貪婪算法切分節點:
紅箭頭表示每一次的切分節點,選擇目標函數降低最大的點做爲切分節點。
3. 切分點算法之分位點算法
若特徵是連續值,按照上述的貪婪算法,運算量極大 。當樣本量足夠大的時候,使用特徵分位點來切分特徵。流程圖以下:
【例】下表表示樣本的某一列特徵數值,用三分位做爲切分節點 。
根據特徵大小進行樣本排序:
用特徵的三分位點做切分節點:
紅箭頭表示每一次的切分節點,選擇目標函數降低最大的點做爲切分節點。
4. 切分點算法之權重分位點算法
上節假設樣本權重相等,根據樣本的分位點來均分損失函數存在誤差,本節用樣本權重來均分損失函數。
損失函數以下:
對其變形獲得:
xi損失函數能夠看作是以以−gi/hi做爲label的均方偏差,乘以大小hi的權重,換句話說,xi對loss的貢獻權重爲hi ,構建樣本權重的分位點等於偏差的均分。
上節假設樣本權重相等,特徵值的分位點做爲切分點,本節假設樣本權重是hi,構建樣本權重的均分點步驟:
(1)根據特徵大小對樣本進行排序
(2)定義排序函數:
其中x,z表示特徵
(3)設置排序函數的分位點爲切分點
【例】以下圖
特徵與對應的排序函數值的關係,以下表:
紅色箭頭表示以三分位點做爲切分點。
最後,選擇最優切分點。
5. 稀疏數據的切分算法
稀疏數據在實際項目是很是常見,形成稀疏數據的緣由主要有:1. 數據缺失;2. 統計上的 0;3. one-hot編碼的特徵表示。
稀疏數據的切分點算法:
當出現特徵值缺失時,包含缺失特徵值的樣本被映射到默認的方向分支,而後計算該節點的最優切分點,最優切分點對應的默認切分方向就是特徵值缺失時默認的方向。
目錄
XGBoost算法原理簡單回顧
XGBoost的優勢
XGBoost的參數解釋
參數調優實例
小結
1. XGBoost算法原理簡單回顧
XGBoost算法的每顆樹都是對前一個模型損失函數的二階導展開式擬合,而後結合多棵樹給出分類或迴歸結果。所以咱們只要知道每棵樹的構建過程,就能很好的理解XGBoost的算法原理。
假設對於前t-1棵樹的預測結果爲,真實結果爲y,用L表示損失函數,那麼當前模型的損失函數爲:
XGBoost法構建樹的同時考慮了正則化,定義每棵樹的複雜度爲:
所以,包含正則化項的損失函數爲:
最小化(1.3)式獲得最終的目標函數:
目標函數也稱爲打分函數,它是衡量樹結構好壞的標準,值越小表明樹的結構越好。所以樹的節點切分規則是選擇樹目標函數值降低最大的點做爲切分點 。
以下圖,對於某一節點切分先後的目標函數之差記爲Gain。
選擇Gain降低最大的切分點對樹分裂,以此類推,獲得完整的樹 。
所以,只要知道(1.5)式的參數值就能基本肯定樹模型,其中表示左子節點損失函數的二階導之和,
表示右子節點損失函數的二階導之和,
表示左子節點損失函數的一階導之和,
表示右子節點損失函數的一階導之和 。
表示正則化係數,
表示切分節點難度,
和
定義了樹的複雜度。再簡單一點,咱們只要設置了損失函數L,正則化係數
和切分節點難度
,就基本肯定了樹模型 。XGBoost參數擇要重點考慮這三個參數 。
2. XGBoost的優勢
1. 正則化
XGBoost切分節點時考慮了正則化項(如圖1.3),減小了過擬合。實際上,XGBoost也稱爲「正則化提高」技術。
2. 並行處理
雖然XGBoost是串行迭代生成各決策樹,可是咱們在切分節點時能夠作到並行處理 ,所以XGBoost支持Hadoop實現 。
3. 高度靈活性
XGBoost支持自定義目標函數和評價函數,評價函數是衡量模型好壞的標準,目標函數是損失函數,如上節討論,只要知道了損失函數,而後求其一階導和二階導,就能肯定節點的切分規則。
4. 缺失值處理
XGBoost內置了處理缺失值的節點切分規則 。用戶須要提供一個和其餘樣本不同的值(如-999), 而後把該值做爲參數的缺失值 。
5. 內置交叉驗證
XGBoost容許每一輪迭代中使用交叉驗證,所以,能夠很方便的得到交叉驗證率,獲得最優boosting迭代次數 ,並不須要傳統的網格搜索法來獲取最優迭代次數 。
6. 在已有的模型基礎上繼續
XGBoost能夠從上一輪的結果上繼續訓練,從而節省了運行時間,經過設置模型參數「process_type」= update來實現 。
3. XGBoost參數解釋
XGBoost參數把全部的參數分爲三類:
1. 通用參數:控制了模型的宏觀功能 。
2. Booster參數:控制每一輪迭代的樹生成。
3. 學習目標參數:決定了學習場景,如損失函數和評價函數 。
3.1 通用參數
booster [default = gbtree]
供選擇的模型有gbtree和gblinear,gbtree使用基於樹的模型進行提高,gblinear使用線性模型進行提高,默認是gbtree 。這裏只介紹tree booster,由於它的表現遠遠賽過linear booster
silent [default = 0]
取0時表示打印運行信息,取1時表示不打印運行信息。
nthread
XGBoost運行時的線程數,默認是當前系統可運行的最大線程數。
num_pbuffer
預測數據的緩衝區大小,通常設置成訓練樣本個數的大小 。緩衝區保留最後一次迭代後的預測結果,系統自動設置。
num_feature
設置特徵維數來構建樹模型,系統自動設置 。
3.2 booster參數
eta [default = 0.3]
控制樹模型的權重,與AdaBoost算法的學習率(learning rate)含義相似,縮小權重以免模型處於過擬合,在對eta進行參數擇優時,須要與迭代次數(num_boosting_rounding)結合在一塊兒考慮 ,如減少學習率,那麼增長最大迭代次數;反之,則減少最大迭代次數 。
範圍:[0,1]
模型迭代公式:
其中表示前t棵樹結合模型的輸出結果,
表示第t棵樹模型,α表示學習率,控制模型更新的權重 。
gamma [default = 0]
控制模型切分節點的最小損失函數值,對應(1.5)式的γ,若γ設置的過大(1.5)式小於零,則不進行節點切分,所以下降了模型的複雜度。
lambda [default = 1]
表示L2正則化參數,對應(1.5)式中的λ,增大λ的值使模型更保守,避免過擬合 。
alpha [default = 0]
表示L1正則化參數,L1正則化的意義在於能夠降維,增大alpha值使模型更保守,避免過擬合
範圍:[0,∞]
max_depth [default=6]
表示樹的最大深度,增長樹的深度提升了樹的複雜度,頗有可能會致使過擬合,0表示對樹的最大深度無限制 。
範圍:[0,∞]
min_child_weight [default=1]
表示最小葉子節點的樣本權重和,和以前介紹的min_child_leaf參數有差異,min_child_weight表示樣本權重的和,min_child_leaf表示樣本總數和。
範圍:[0,∞]
subsample [default=1]
表示隨機採樣必定比例的樣原本構建每棵樹,減少比例參數subsample值,算法會更加保守,避免過擬合
範圍:[0,1]
colsample_bytree,colsample_bylevel,colsample_bynode
這個三個參數表示對特徵進行隨機抽樣,且具備累積效應 。
colsample_bytree,表示每棵樹劃分的特徵比重
colsample_bylevel,表示樹的每層劃分的特徵比重
colsample_bynode,表示樹的每一個節點劃分的特徵比重 。
好比,樣本共有64個特徵,設置{'colsample_bytree' : 0.5 , 'colsample_bylevel' : 0.5 , 'colsample_bynode' : 0.5 },那麼隨機採樣4個特徵應用於樹的每個節點切分 。
範圍:[0,1]
tree_method string [default = auto ]
表示樹的構建方法,確切來講是切分點的選擇算法,包括貪心算法,近似貪心算法,直方圖算法
exact:貪心算法
aprrox:近似貪心算法,選擇特徵的分位點進行切分
hist:直方圖切分算法,LightGBM算法也採用該切分算法 。
scale_pos_weight [default = 1]
當正負樣本不平衡時,設置該參數爲正值 ,能夠使算法更快收斂 。
典型的值可設置爲:(負樣本個數)/(正樣本個數)
process_type [default = default]
default:正常的構建提高樹過程
update: 從已有的模型構建提高樹
3.3 學習任務參數
根據任務和目的設置參數
objective,訓練目標,分類仍是迴歸
reg : linear,線性迴歸
reg : logistic,邏輯迴歸
binary : logistic,使用LR二分類,輸出機率
binary : logitraw,使用LR二分類,輸出Logistic轉換以前的分類得分 。
eval_metric,評價驗證集的指標,默認根據目標函數設置,默認狀況下,最小均方差用於迴歸,錯誤率用於分類,平均精確率用於排序 。
rmse:均方差
mae:平均絕對值偏差
error :錯誤率
logloss:負的對數損失
auc : roc曲線下的面積
seed [default=0]
隨機數種子,設置它能夠復現隨機數據結果 。
4. 參數調優實例
原始數據集和通過特徵工程處理後的數據集在開頭的連接部分進行下載,算法在jupter-notebook交互界面開發 。
定義模型評價函數,並根據必定的學習率獲得最優迭代次數 ,函數定義以下:
Step1:
根據經驗設置默認的參數,調用modelfit函數獲得最優迭代次數是198 。
Step2: 樹最大深度和最小葉子節點權重調優
根據第一步獲得的最優迭代次數更新模型參數n_estimators,而後調用model_selection類的GridSearchCV設置交叉驗證模型,最後調用XGBClassifier類的fit函數獲得最優樹的最大深度和最小葉子節點權重 。
a) 設置樹最大深度和最小葉子節點權重範圍:
b) GridSearchCV設置交叉驗證模型:
c) XGBClassfier類的fit函數更新參數:
Step3: gamma參數調優
Step4: subsample and colsample_bytree參數調優
Step5: 正則化參數調優
Step3,Step4和Step5參數調優思想Step2一致,這裏再也不展開,可參考代碼去理解 。
Step6: 減少學習率,增大對應的最大迭代次數 。參數調優思想與Step1一致,獲得最優的迭代次數 ,並輸出交叉驗證率結果。
迭代次數爲2346時,獲得最優分類結果(以下圖)。
5. XGBoost參數調優小結
XGBoost是一個高性能的學習模型算法,當你不知道怎麼對模型進行參數調優時,可參考上一節的步驟去進行參數調優 。本節根據上節的內容,以及本身的項目經驗闡述一下本人對XGBoost算法參數調優的一些理解,如有錯誤之處,還忘指正 。
(1)模型初始化 。在初始化模型參數時,咱們儘可能讓模型的複雜度較高,而後一步一步的經過參數調優來下降模型複雜度 。如上節初始化參數:葉子節點最小權重爲0,最大樹深度爲5,最小損失函數降低值爲0,這些參數初始化都是複雜化模型 。
(2) 學習率和最大迭代次數 。這兩個參數的調優必定是聯繫在一塊兒的,學習率越大,達到相同性能的模型所須要的最大迭代次數越小;學習率越小,達到相同性能的模型所須要的最大迭代次數越大 。XGBoost每一個參數的更新都須要進行屢次迭代,所以,學習率和最大迭代次數是首先須要考慮的參數 ,且學習率和最大迭代參數的重點不是提升模型的分類準確率,而是提升模型的泛化能力,所以,當模型的分類準確率很高時,咱們最後一步應減少學習率的大小,以提升模型的泛化能力 。
(3) 逐步下降模型複雜度 。樹的最大深度,葉子節點最小權重等參數都是影響模型複雜度的因素,這個看本身經驗,第四節的調參順序是:樹的最大深度和葉子節點最小權重->最小損失函數降低值->行採樣和列採樣->正則化參數 。實際項目中,我通常按照這個順序去調參 ,如有不一樣的理解,歡迎交流。
(4) 特徵工程:若模型的準確率在很低的範圍,那麼我建議先不用去調參了,去重點關注特徵和訓練數據。特徵和數據決定模型上限,模型只是逼近這個上限 。
提高樹是利用加法模型和前向分佈算法實現學習的優化過程,它有一些高效的實現,如GBDT,XGBoost和pGBRT,其中GBDT是經過損失函數的負梯度擬合殘差,XGBoost則是利用損失函數的二階導展開式擬合殘差。可是,當面對大量數據集和高維特徵時,其擴展性和效率很難使人滿意,最主要的緣由是對於每個特徵,它們須要掃描全部的樣本數據來得到最優切分點,這個過程是很是耗時的 。而基於GBDT的另外一種形式LightGBM基於直方圖的切分點算法,其很好的解決了這些問題
目錄
1. 基於直方圖的切分點算法
算法流程圖以下:
流程解釋:LightGBM經過直方圖算法把連續的特徵值離散化成對應的bin(能夠理解成桶),而後累加每一個bin對應特徵的梯度值並計數,最後遍歷全部特徵和數據,尋找最優切分點 。下面詳細解釋這一過程 。
1) 直方圖算法:
直方圖經過分段函數把連續值離散化成對應的bin。
如分段函數爲:
那麼,對於連續值≥0的特徵分紅四個桶,特徵的全部可能切分點個數降爲4,即bin的個數 ,所以大大加快了訓練速度。
直方圖每一個bin包含了兩類信息,分別是每一個bin樣本中的梯度之和與每一個bin中的樣本數量,對應於流程圖的表達式:
每一個bin累加的梯度包含了 一階梯度與二階梯度
2)切分點算法:
LightGBM和XGBoost的切分點算法思想是同樣的,比較切分後的增益與設定的最小增益的大小,若大於,則切分;反之,則不切分該節點。下面詳細敘述這一過程(該節代碼實現均在LightGBM/src/treelearner/feature_histogram.hpp):
(1)計算每一個葉子節點的輸出wj;
根據上面兩圖的代碼,可知lightGBM的葉子節點輸出與XGBoost相似,即:
其中,Gj爲葉子節點包含全部樣本的一階梯度之和,Hj爲二階梯度之和 。
(2)計算節點切分後的分數
葉子節點分數爲GetLeafSplitGainGivenOutput函數:
其中output表明葉子節點輸出Wj 。考慮通常狀況,假如葉子節點的樣本一階梯度和大於l1,那麼,葉子節點分數的表達式爲:
節點切分前的分數:
所以,計算節點切分增益:
節點切分增益= 節點分數 - (左葉子節點分數 + 右葉子節點分數)
比較切分增益與設置的最小增益大小,記爲Gain:
Gain = 節點切分增益 — 最小切分增益
最後獲得與XGBoost相似的形式,XGBoost爲以下形式:
LightGBM的最小切分增益對應於XGBoost的γ 。
2.直方圖算法改進
直方圖算法經過分段函數把連續值離散化成對應的bin的複雜度爲O(#feature×#data),若下降feature或data的大小,那麼直方圖算法的複雜度也相應的下降,微軟開源的LightGBM提供了兩個算法分別下降feature和data的大小:
1. GOSS(減小樣本角度):保留梯度較大的樣本數,減小梯度較小的樣本個數 。樣本訓練偏差小,表示該樣本獲得了很好的訓練,對應的梯度亦越小 。一種直接的想法是拋棄這些梯度較小的樣本,可是這種處理方法會改變樣本集的分佈,下降了訓練模型的準確率(由於丟棄的都是損失偏差較小的樣本) 。所以,咱們建議採用一種名爲GOSS的方法,即GOSS保留具備大梯度的樣本數,對梯度較小的樣本進行隨機採樣,爲了彌補數據集分佈改變的影響,GOSS對小梯度的樣本數增長了權重常數 。
GOSS僞代碼以下:
參考GOSS的解釋,僞代碼應該比較容易理解吧!
僞代碼中損失函數的梯度g表明的含義是一階梯度和二階梯度的乘積,見Github的實現( LightGBM/src/boosting/goss.hpp)。
2. EFB(從減小特徵角度):捆綁(bundling)互斥特徵,用一個特徵代替多個互斥特徵,達到減小特徵個數的目的 。EFB算法須要解決兩個問題,(1)捆綁互斥特徵,(2)合併互斥特徵 。這裏就不詳細介紹了。
3. 直方圖作差優化
一個葉子節點的直方圖能夠由父親節點的直方圖與它兄弟的直方圖作差獲得 。利用這個方法,LightGBM能夠用父親節點的直方圖減去數據量比較小的葉子節點直方圖,獲得數據量比較大的葉子節點直方圖,由於該直方圖是作差獲得的,時間複雜度僅爲O(#bins),比起不作差獲得的兄弟節點的直方圖,速度上能夠提高一倍。
直方圖作差示意圖以下:
4. 樹的生長策略
XGBoost是按層生長(level-wise)的方式展開節點,優勢是不容易過擬合,缺點是它對每一層葉子節點不加區分的進行展開,實際上某些葉子節點的分裂增益較低,不必進行搜索和分裂。以下圖所示:
LightGBM是按最大增益的節點(葉子明智,Leaf-wise)進行展開,這樣作的好處是找到分裂增益最大的葉子節點進行分裂,如此循環 。優勢是效率高,在分裂次數相同的狀況下,Leaf-wise能夠獲得更高的準確率 。缺點是可能會產生過擬合,經過設置樹的最大生長深度避免 。以下圖所示:
5. 支持類別特徵
類別特徵在實際項目中比較常見,XGBoost經過one-hot編碼把類別特徵轉化爲多維特徵,下降了算法運行效率,LightGBM優化了類別特徵的支持,不須要對類別特徵進行one-hot編碼 。
6. 支持高效並行
LightGBM支持特徵並行和數據並行 。
特徵並行:在不一樣機器選擇局部不一樣特徵對應的最優切分點,而後同步各機器結果,選擇最優切分點 。以下圖:
LightGBM對特徵並行進行了優化,經過在本地保存所有數據避免對數據切分結果的通訊 。
數據並行:不一樣機器在本地構造直方圖,而後進行全局的合併,最後在合併的直方圖上尋找最優分割點。以下圖:
LightGBM有下面兩種優化數據並行的方法:
(1)LightGBM經過"Reduce Scatter"將把直方圖合併的任務分攤到不一樣的機器,下降通訊和計算,並利用直方圖作差,進一步減小了一半的通訊量 。
(2)LightGBM經過「PV-Tree」的算法進行投票並行(Voting Parallel),使通訊開銷變成常數級別,在數據量很大的時候,使用投票並行能夠獲得很是好的加速效果。以下圖:
7. 與XGBoost的對比
LightGBM相對於XGboost具備更快的訓練效率和更低的內存使用,以下對比圖:
LightGBM內存開銷下降到原來的1/8倍 ,在Expo數據集上速度快了8倍和在Higg數據集上加速了40%,
【Abstract】
Gradient Boosting Decision Tree (GBDT)很是流行卻鮮有實現,只有像XGBoost和pGBRT。當特徵維度較高和數據量巨大的時候,其實現中仍然存在效率和可擴展性的問題。一個主要緣由就是對於每個特徵的每個分裂點,都須要遍歷所有數據計算信息增益,這一過程很是耗時。針對這一問題,本文提出兩種新方法:Gradient-based One-Side Sampling (GOSS) 和Exclusive Feature Bundling (EFB)(基於梯度的one-side採樣和互斥的特徵捆綁)。在GOSS中,咱們排除了重要的比例-具備小梯度的實例,只用剩下的來估計信息增益,咱們證實,這些梯度大的實例在計算信息增益中扮演重要角色,GOSS能夠用更小的數據量對信息增益進行至關準確的估計。對於EFB,咱們捆綁互斥的特徵(什麼是互斥特徵:例如特徵間不多同時非零。),來下降特徵的個數。咱們證實完美地捆綁互斥特徵是NP難的,但貪心算法可以實現至關好的逼近率,所以咱們可以在不損害分割點準確率許多,有效減小特徵的數量。(犧牲一點分割準確率下降特徵數量),這一算法命名爲LightGBM。在多個公共數據集實驗證實,LightGBM加速了傳統GBDT訓練過程20倍以上,同時達到了幾乎相同的精度 。
1. Introduction
GBDT由於其的有效性、準確性、可解釋性,成爲了普遍使用的機器學習算法。GBDT在許多機器學習任務上取得了最好的效果( state-of-the-art),例如多分類,點擊預測,排序。但最近幾年隨着大數據的爆發(特徵量和數據量),GBDT面臨平衡準確率和效率的調整。
GBDT缺點:對於每個特徵的每個分裂點,都須要遍歷所有數據來計算信息增益。所以,其計算複雜度將受到特徵數量和數據量雙重影響,形成處理大數據時十分耗時。
解決這個問題的直接方法就是減小特徵量和數據量並且不影響精確度,有部分工做根據數據權重採樣來加速boosting的過程,但因爲gbdt沒有樣本權重不能應用。而本文提出兩種新方法實現此目標。
Gradient-based One-Side Sampling (GOSS):GBDT雖然沒有數據權重,但每一個數據實例有不一樣的梯度,根據計算信息增益的定義,梯度大的實例對信息增益有更大的影響,所以在下采樣時,咱們應該儘可能保留梯度大的樣本(預先設定閾值,或者最高百分位間),隨機去掉梯度小的樣本。咱們證實此措施在相同的採樣率下比隨機採樣得到更準確的結果,尤爲是在信息增益範圍較大時。
Exclusive Feature Bundling (EFB):一般在真實應用中,雖然特徵量比較多,可是因爲特徵空間十分稀疏,是否能夠設計一種無損的方法來減小有效特徵呢?特別在稀疏特徵空間上,許多特徵幾乎是互斥的(例如許多特徵不會同時爲非零值,像one-hot),咱們能夠捆綁互斥的特徵。最後,咱們將捆綁問題歸約到圖着色問題,經過貪心算法求得近似解。
2. Preliminaries
2.1 GBDT and Its Complexity Analysis
GBDT是一種集成模型的決策樹,順序訓練決策樹。每次迭代中,GBDT經過擬合負梯度(殘差)來學到決策樹。
學習決策樹是GBDT主要的時間花銷,而學習決策樹中找到最優切分點最消耗時間。普遍採用的預排序算法來找到最優切分點,這種方法會列舉預排序中全部可能的切分點。這種算法雖然可以找到最優的切分點,但對於訓練速度和內存消耗上都效率低。另外一種流行算法是直方圖算法(histogram-based algorithm)。直方圖算法並不經過特徵排序找到最優的切分點,而是將連續的特徵值抽象成離散的分箱,並使用這些分箱在訓練過程當中構建特徵直方圖,這種算法更加訓練速度和內存消耗上都更加高效,lightGBM使用此種算法。
histogram-based算法經過直方圖尋找最優切分點,其建直方圖消耗O(#data * #feature),尋找最優切分點消耗O(#bin * # feature),而#bin的數量遠小於#data,因此建直方圖爲主要時間消耗。若是可以減小數據量或特徵量,那麼還可以夠加速GBDT的訓練。
2.2 Related Work
GBDT有許多實現,如XGBoost,PGBRT,Scikit-learn,gbm in R。Scikit-learn和gbm in R實現都用了預排序,pGBRT使用了直方圖算法,XGBoost支持預排序和直方圖算法,因爲XGBoost賽過其餘算法,咱們用它做爲baseline。
爲了減少訓練數據集,一般作法是下采樣。例如過濾掉權重小於閾值的數據。SGB每次迭代中用隨機子集訓練弱學習器。或者採樣率基於訓練過程動態調整。除了基於AdaBoost的SGB不能直接應用於GBDT,由於GBDT中沒有原始的權重。雖然SGB也能間接應用於GBDT,但每每會影響精度。
一樣,過濾掉弱特徵(什麼是弱特徵)來減小特徵量。一般用主成分分析或者投影法。固然,這些方法依賴於一個假設-特徵包含高度的冗餘,但實際中每每不是。(設計特徵來自於其獨特的貢獻,移除任一維度均可以某種程度上影響精度)。
實際中大規模的數據集一般都是很是稀疏的,使用預排序算法的GBDT可以經過無視爲0的特徵來下降訓練時間消耗。而後直方圖算法沒有優化稀疏的方案。由於直方圖算法不管特徵值是否爲0,都須要爲每一個數據檢索特徵區間值。若是基於直方圖的GBDT可以有效利用稀疏特徵將是最優。
下圖是兩個算法的對比:
3. Gradient-based One-Side Sampling
GOSS是一種在減小數據量和保證精度上平衡的算法。
3.1 Algorithm Description
AdaBoost中,樣本權重是數據實例重要性的指標。然而在GBDT中沒有原始樣本權重,不能應用權重採樣。幸運的事,咱們觀察到GBDT中每一個數據都有不一樣的梯度值,對採樣十分有用,即實例的梯度小,實例訓練偏差也就較小,已經被學習得很好了,直接想法就是丟掉這部分梯度小的數據。然而這樣作會改變數據的分佈,將會影響訓練的模型的精確度,爲了不此問題,咱們提出了GOSS。
GOSS保留全部的梯度較大的實例,在梯度小的實例上使用隨機採樣。爲了抵消對數據分佈的影響,計算信息增益的時候,GOSS對小梯度的數據引入常量乘數。GOSS首先根據數據的梯度絕對值排序,選取top a個實例。而後在剩餘的數據中隨機採樣b個實例。接着計算信息增益時爲採樣出的小梯度數據乘以(1-a)/b,這樣算法就會更關注訓練不足的實例,而不會過多改變原數據集的分佈。
GBDT使用決策樹,來學習得到一個將輸入空間映射到梯度空間的函數。假設訓練集有n個實例x1,...,xn,特徵維度爲s。每次梯度迭代時,模型數據變量的損失函數的負梯度方向爲g1,...,gn,決策樹經過最優切分點(最大信息增益點)將數據分到各個節點。GBDT經過分割後的方差衡量信息增益。
定義3.1:O表示某個固定節點的訓練集,分割特徵 j 的分割點d定義爲:
其中,
遍歷每一個特徵分裂點 j,找到
對應最大的分裂節點,並計算最大的信息增益。而後,將數據根據特徵
的分裂點
將數據分到左右節點。
在GOSS中,
1. 首先根據數據的梯度將訓練降序排序。
2. 保留top a個數據實例,做爲數據子集A。
3. 對於剩下的數據的實例,隨機採樣得到大小爲b的數據子集B。
4. 最後咱們經過如下方程估計信息增益:
此處GOSS經過較小的數據集估計信息增益,將大大地減少計算量。更重要的是,咱們接下來理論代表GOSS不會丟失許多訓練精度,賽過(outperform)隨機採樣。理論的證實再附加材料。
Theorem 3.2 咱們定義GOSS近似偏差爲:,且
,
機率至少是1−δ,有:
其中:
根據理論3.2,咱們得出如下結論:
1. GOSS的漸進逼近比率是:
若是數據分割不是極不平衡,好比:
且
近似偏差主要由第二項主導,當n趨於無窮(數據量很大)時,
趨於0。即數據量越大,偏差越小,精度越高。
2. 隨機採樣是GOSS在a=0的一種狀況。多數狀況下,GOSS性能優於隨機採樣,即如下狀況:
即:
其中,
下面分析GOSS的泛化性。考慮GOSS泛化偏差:
這是GOSS抽樣的的實例計算出的方差增益與實際樣本方差增益之間的差距。
變換爲:
所以,在GOSS準確的狀況下,GOSS泛化偏差近似於全數據量的真實數據。另外一方面,採樣將增長基學習器的多樣性(由於每次採樣得到的數據可能會不一樣),這將提升泛化性。
4. Exclusive Feature Bundling
這一章介紹如何有效減小特徵的數量
高維的數據一般是稀疏的,這種稀疏性啓發咱們設計一種無損地方法來減小特徵的維度。特別的,稀疏特徵空間中,許多特徵是互斥的,例如他們從不一樣時爲非零值。咱們能夠綁定互斥的特徵爲單一特徵,經過仔細設計特徵搜尋算法,咱們從特徵捆綁中構建了與單個特徵相同的特徵直方圖。這種方式的間直方圖時間複雜度從O(#data * #feature)降到O(#data * #bundle),因爲#bundle << # feature,咱們可以極大地加速GBDT的訓練過程並且損失精度。
有兩個問題:
1. 怎麼斷定那些特徵應該綁在一塊兒(build bundled)?
2. 怎麼把特徵綁爲一個(merge feature)?
**理論 4.1:**將特徵分割爲較小量的互斥特徵羣是NP難的。
證實:將圖着色問題歸約爲此問題,而圖着色是NP難的,因此此問題就是NP難的。
給定圖着色實例G=(V, E)。以G的關聯矩陣的每一行爲特徵,獲得咱們問題的一個實例有|V|個特徵。 很容易看到,在咱們的問題中,一個獨特的特徵包與一組具備相同顏色的頂點相對應,反之亦然。
理論4.1說明多項式時間中求解這個NP難問題不可行。爲了尋找好的近似算法,咱們將最優捆綁問題歸結爲圖着色問題,若是兩個特徵之間不是相互排斥,那麼咱們用一個邊將他們鏈接,而後用合理的貪婪算法(具備恆定的近似比)用於圖着色來作特徵捆綁。 此外,咱們注意到一般有不少特徵,儘管不是100%相互排斥的,也不多同時取非零值。 若是咱們的算法能夠容許一小部分的衝突,咱們能夠獲得更少的特徵包,進一步提升計算效率。通過簡單的計算,隨機污染小部分特徵值將影響精度最多爲:
γ是每一個綁定中的最大沖突比率,當其相對較小時,可以完成精度和效率之間的平衡。
**算法3:**基於上面的討論,咱們設計了算法3,僞代碼見下圖,具體算法:
1.創建一個圖,每一個點表明特徵,每一個邊有權重,其權重和特徵之間整體衝突相關。
2. 按照降序排列圖中的度數來排序特徵。
3. 檢查排序以後的每一個特徵,對他進行特徵綁定或者創建新的綁定使得操做以後的整體衝突最小。
算法3的時間複雜度是O(#feature^2),訓練以前只處理一次,其時間複雜度在特徵不是特別多的狀況下是能夠接受的,但難以應對百萬維的特徵。爲了繼續提升效率,咱們提出了一個更加高效的無圖的排序策略:將特徵按照非零值個數排序,這和使用圖節點的度排序類似,由於更多的非零值一般會致使衝突,新算法在算法3基礎上改變了排序策略。
4.2 merging features(特徵合併)
如何合併同一個bundle的特徵來下降訓練時間複雜度。關鍵在於原始特徵值能夠從bundle中區分出來。鑑於直方圖算法存儲離散值而不是連續特徵值,咱們經過將互斥特徵放在不一樣的箱中來構建bundle。這能夠經過將偏移量添加到特徵原始值中實現,例如,假設bundle中有兩個特徵,原始特徵A取值[0, 10],B取值[0, 20]。咱們添加偏移量10到B中,所以B取值[10, 30]。經過這種作法,就能夠安全地將A、B特徵合併,使用一個取值[0, 30]的特徵取代AB。算法見算法4,
EFB算法可以將許多互斥的特徵變爲低維稠密的特徵,就可以有效的避免沒必要要0值特徵的計算。實際,經過用表記錄數據中的非零值,來忽略零值特徵,達到優化基礎的直方圖算法。經過掃描表中的數據,建直方圖的時間複雜度將從O(#data)降到O(#non_zero_data)。固然,這種方法在構建樹過程當中須要而額外的內存和計算開銷來維持預特徵表。咱們在lightGBM中將此優化做爲基本函數,由於當bundles是稀疏的時候,這個優化與EFB不衝突(能夠用於EFB)。
5. Experiments
這部分主要寫了lightGBM的實驗結果,主要用了五個公開數據集,以下
微軟的排序數據集(LETOR)包括30K的網頁搜索,數據集幾乎都是稠密的數值特徵。
Allstate是保險和航空延誤數據都包含了大量的one-hot特徵。
後兩個是KDD CUP2010和KDD CPU2012數據集,使用了冠軍解決方案中的特徵,其中包含了稀疏和稠密的特徵,而且這兩個數據集特別大。
這些數據集都比較大,並且包含了稀疏和稠密的特徵,涵蓋了不少真實的業務,所以它們可以徹底地測試lightGBM的性能。
XGBoost和lightGBM without GOSS 和EFB(lgb baseline),做爲比較的基準。XGBoost使用了兩個版本:xgb_exa(預排序)和xgb_his(直方圖算法)。對於xgb_exa作了參數調整,使XGBoost長成和其餘算法類似的樹。而且調整參數在速度和準確率間平衡。對於Allstate、KDD10 和 KDD2012,設置a = 0.05 , b = 0.05 ,對於航空延誤和LETOR,咱們設置a = 0.1 , b = 0.1 ,數據集EFB咱們設置γ = 0 。全部的算法有固定迭代次數。在必定迭代次數內,咱們取最高的分數。
下表是訓練時間對比(時間是每次迭代的平均時間)
下表是精確度對比,分類使用AUC評價,排序使用NDCG評價。
下圖是飛行延時和LETOR的訓練曲線。
5.2 Analysis on GOSS
**速度上:**GOSS具備加速訓練的能力,表2中能夠看出GOSS幾乎加速了兩倍。雖然GOSS用了10%-20%的數據訓練,可是因爲有一些額外的計算,因此加速並不和數據量成反比,可是GOSS仍然極大加速了訓練。
**精度上:**從表4中能夠看出,一樣採樣率,GOSS精度總比SGB好。
5.3 Analysis on EFB
表2代表,EFB在大數據集上可以極大加速訓練。由於EFB合併大量的稀疏特徵到低維稠密的特徵,而且因爲以前的孤立的特徵被bundle到一塊兒,能可以極大提升緩存的命中率,所以,它所有的效率提升是動態的。
綜上這些分析,EFB是改進直方圖算法稀疏性的很是高效的算法,可以極大地加速GBDT訓練。
6. Conclusion
本文提出了新穎的GBDT算法–LightGBM,它包含了連個新穎的技術:Gradient-based One-Side Sampling (GOSS) 和Exclusive Feature Bundling (EFB)(基於梯度的one-side採樣和互斥的特徵捆綁)來處理大數據量和高維特徵的場景。咱們在理論分析和實驗研究代表,GOSS和EFB使得LightGBM在計算速度和內存消耗上明顯優於XGBoost和SGB。
將來,咱們將研究優化如何在GOSS中選擇a,b。繼續提升EFB在高維特徵上的性能,不管其是不是稀疏的。
一、LightGBM簡介
LightGBM是一個梯度Boosting框架,使用基於決策樹的學習算法。它能夠說是分佈式的,高效的,有如下優點:
1)更快的訓練效率
2)低內存使用
3)更高的準確率
4)支持並行化學習
5)能夠處理大規模數據
與常見的機器學習算法對比,速度是很是快的
二、XGboost的缺點
在討論LightGBM時,不可避免的會提到XGboost,關於XGboost能夠參考此博文
關於XGboost的不足之處主要有:
1)每輪迭代時,都須要遍歷整個訓練數據屢次。若是把整個訓練數據裝進內存則會限制訓練數據的大小;若是不裝進內存,反覆地讀寫訓練數據又會消耗很是大的時間。
2)預排序方法的時間和空間的消耗都很大
三、LightGBM原理
1)直方圖算法
直方圖算法的基本思想是先把連續的浮點特徵值離散化成k個整數,同時構造一個寬度爲k的直方圖。在遍歷數據的時候,根據離散化後的值做爲索引在直方圖中累積統計量,當遍歷一次數據後,直方圖累積了須要的統計量,而後根據直方圖的離散值,遍歷尋找最優的分割點。
使用直方圖算法有不少優勢。首先,最明顯就是內存消耗的下降,直方圖算法不只不須要額外存儲預排序的結果,並且能夠只保存特徵離散化後的值,而這個值通常用8位整型存儲就足夠了,內存消耗能夠下降爲原來的1/8。
而後在計算上的代價也大幅下降,預排序算法每遍歷一個特徵值就須要計算一次分裂的增益,而直方圖算法只須要計算k次(k能夠認爲是常數),時間複雜度從O(#data * #feature) 優化到O(k* #features)。
固然,Histogram算法並非完美的。因爲特徵被離散化後,找到的並非很精確的分割點,因此會對結果產生影響。但在不一樣的數據集上的結果代表,離散化的分割點對最終的精度影響並非很大,甚至有時候會更好一點。緣由是決策樹原本就是弱模型,分割點是否是精確並非過重要;較粗的分割點也有正則化的效果,能夠有效地防止過擬合;即便單棵樹的訓練偏差比精確分割的算法稍大,但在梯度提高(Gradient Boosting)的框架下沒有太大的影響。
2)LightGBM的直方圖作差加速
一個容易觀察到的現象:一個葉子的直方圖能夠由它的父親節點的直方圖與它兄弟的直方圖作差獲得。一般構造直方圖,須要遍歷該葉子上的全部數據,但直方圖作差僅需遍歷直方圖的k個桶。利用這個方法,LightGBM能夠在構造一個葉子的直方圖後,能夠用很是微小的代價獲得它兄弟葉子的直方圖,在速度上能夠提高一倍。
3)帶深度限制的Leaf-wise的葉子生長策略
Level-wise過一次數據能夠同時分裂同一層的葉子,容易進行多線程優化,也好控制模型複雜度,不容易過擬合。但實際上Level-wise是一種低效的算法,由於它不加區分的對待同一層的葉子,帶來了不少不必的開銷,由於實際上不少葉子的分裂增益較低,不必進行搜索和分裂。
Leaf-wise則是一種更爲高效的策略,每次從當前全部葉子中,找到分裂增益最大的一個葉子,而後分裂,如此循環。所以同Level-wise相比,在分裂次數相同的狀況下,Leaf-wise能夠下降更多的偏差,獲得更好的精度。Leaf-wise的缺點是可能會長出比較深的決策樹,產生過擬合。所以LightGBM在Leaf-wise之上增長了一個最大深度的限制,在保證高效率的同時防止過擬合。
4)直接支持類別特徵(即不須要作one-hot編碼)
實際上大多數機器學習工具都沒法直接支持類別特徵,通常須要把類別特徵,轉化到多維的one-hot編碼特徵,下降了空間和時間的效率。而類別特徵的使用是在實踐中很經常使用的。基於這個考慮,LightGBM優化了對類別特徵的支持,能夠直接輸入類別特徵,不須要額外的one-hot編碼展開。並在決策樹算法上增長了類別特徵的決策規則。在Expo數據集上的實驗,相比0/1展開的方法,訓練速度能夠加速8倍,而且精度一致。
5)直接支持高效並行
LightGBM還具備支持高效並行的優勢。LightGBM原生支持並行學習,目前支持特徵並行和數據並行的兩種。
特徵並行的主要思想是在不一樣機器在不一樣的特徵集合上分別尋找最優的分割點,而後在機器間同步最優的分割點。
數據並行則是讓不一樣的機器先在本地構造直方圖,而後進行全局的合併,最後在合併的直方圖上面尋找最優分割點。
LightGBM針對這兩種並行方法都作了優化,在特徵並行算法中,經過在本地保存所有數據避免對數據切分結果的通訊;在數據並行中使用分散規約 (Reduce scatter) 把直方圖合併的任務分攤到不一樣的機器,下降通訊和計算,並利用直方圖作差,進一步減小了一半的通訊量。
四、LightGBM參數調優
下面幾張表爲重要參數的含義和如何應用
接下來是調參
下表對應了Faster Spread,better accuracy,over-fitting三種目的時,能夠調整的參數
CatBoost是俄羅斯的搜索巨頭Yandex在2017年開源的機器學習庫,是Gradient Boosting(梯度提高) + Categorical Features(類別型特徵),也是基於梯度提高決策樹的機器學習框架。
1、CatBoost技術介紹
1,類別型特徵的處理
CatBoost採用了一種有效的策略,下降過擬合的同時也保證了所有數據集均可用於學習。也就是對數據集進行隨機排列,計算相同類別值的樣本的平均標籤值時,只是將這個樣本以前的樣本的標籤值歸入計算。
2,特徵組合
爲當前樹構造新的分割點時,CatBoost會採用貪婪的策略考慮組合。對於樹的第一次分割,不考慮任何組合。對於下一個分割,CatBoost將當前樹的全部組合、類別型特徵與數據集中的全部類別型特徵相結合。組合被動態地轉換爲數字。CatBoost還經過如下方式生成數值型特徵和類別型特徵的組合:樹選擇的全部分割點都被視爲具備兩個值的類別型特徵,而且組合方式和類別型特徵同樣。
3,克服梯度誤差
CatBoost,和全部標準梯度提高算法同樣,都是經過構建新樹來擬合當前模型的梯度。然而,全部經典的提高算法都存在由有偏的點態梯度估計引發的過擬合問題。許多利用GBDT技術的算法(例如,XGBoost、LightGBM),構建一棵樹分爲兩個階段:選擇樹結構和在樹結構固定後計算葉子節點的值。爲了選擇最佳的樹結構,算法經過枚舉不一樣的分割,用這些分割構建樹,對獲得的葉子節點中計算值,而後對獲得的樹計算評分,最後選擇最佳的分割。兩個階段葉子節點的值都是被當作梯度[8]或牛頓步長的近似值來計算。CatBoost第一階段採用梯度步長的無偏估計,第二階段使用傳統的GBDT方案執行。
4,快速評分
CatBoost使用oblivious樹做爲基本預測器,這種樹是平衡的,不太容易過擬合。oblivious樹中,每一個葉子節點的索引能夠被編碼爲長度等於樹深度的二進制向量。CatBoost首先將全部浮點特徵、統計信息和獨熱編碼特徵進行二值化,而後使用二進制特徵來計算模型預測值。
任何GBDT算法,對於密集的數值特徵數據集來講,搜索最佳分割是創建決策樹時的主要計算負擔。CatBoost利用oblivious決策樹做爲基礎模型,並將特徵離散化到固定數量的箱子中以減小內存使用。就GPU內存使用而言,CatBoost至少與LightGBM同樣有效。主要改進之處就是利用了一種不依賴於原子操做的直方圖計算方法。
5.2 類別型特徵
CatBoost使用完美哈希來存儲類別特徵的值,以減小內存使用。因爲GPU內存的限制,在CPU RAM中存儲按位壓縮的完美哈希,以及要求的數據流、重疊計算和內存等操做。經過哈希來分組觀察。在每一個組中,咱們須要計算一些統計量的前綴和。該統計量的計算使用分段掃描GPU圖元實現。
5.3 多GPU支持
CatBoost中的GPU實現可支持多個GPU。分佈式樹學習能夠經過數據或特徵進行並行化。CatBoost採用多個學習數據集排列的計算方案,在訓練期間計算分類特徵的統計數據。
2、CatBoost的優勢
性能卓越:在性能方面能夠匹敵任何先進的機器學習算法;
魯棒性/強健性:它減小了對不少超參數調優的需求,並下降了過分擬合的機會,這也使得模型變得更加具備通用性;
易於使用:提供與scikit集成的Python接口,以及R和命令行界面;
實用:能夠處理類別型、數值型特徵;可擴展:支持自定義損失函數;
最近我參加了一個Kaggle比賽(斯坦福大學的WIDS Datathon),依靠各類boosting算法,我最後擠進了前十名。雖然成績很好,但從那以後我就對模型集成學習的細節感到十分好奇:那些模型是怎麼組合的?參數怎麼調整?它們各自的優勢和缺點又是什麼?
考慮到本身曾經用過許多boosting算法,我決定寫一篇文章來重點分析XGBoost、LGBM和CatBoost的綜合表現。雖然最近神經網絡很流行,但就我我的的觀點來看,boosting算法在訓練數據有限時更好用,訓練時間更短,調參所需的專業知識也較少。
XGBoost是陳天奇於2014年提出的一種算法,被稱爲GBM Killer,由於介紹它的文章有不少,因此本文會在介紹CatBoost和LGBM上用更大的篇幅。如下是咱們將要討論的幾個主題:
結構差別
處理分類變量
參數簡介
數據集實現
算法性能
雖然LightGBM和XGBoost都是基於決策樹的boosting算法,但它們之間存在很是顯著的結構差別。
LGBM採用leaf-wise生長策略,也就是基於梯度的單側採樣(GOSS)來找出用於分裂的數據實例,當增加到相同的葉子節點時,LGBM會直接找出分裂增益最大的葉子(一般是數據最大坨的那個),只分裂一個。
LightGBM
而XGBoost採用的則是level(depth)-wise生長策略,它用預排序算法+直方圖算法爲每一層的葉子找出最佳分裂,簡而言之,就是它是不加區分地分裂同一層全部葉子。
XGBoost
咱們先來看看預排序算法(pre-sorted)的工做方式:
對每一個葉子(分割點)遍歷全部特徵;
對每一個特徵,按特徵值對數據點進行排序;
肯定當前特徵的基本分裂增益,用線性掃描決定最佳分裂方法;
基於全部特徵採起最佳分裂方法。
而直方圖算法的工做方式則是根據當前特徵把全部數據點分割稱離散區域,而後利用這些區域查找直方圖的分割值。雖然比起預排序算法那種在排序好的特徵值上枚舉全部可能的分割點的作法,直方圖算法的效率更高,但它在速度上仍是落後於GOSS。
那麼爲何GOSS這麼高效呢?
這裏咱們須要提到經典的AdaBoost。在AdaBoost中,數據點的權重是數據點重要與否的一個直觀指標,但梯度提高決策樹(GBDT)不自帶這種權重,所以也就沒法沿用AdaBoost的採樣方法。
基於梯度的採樣:梯度指的是損失函數切線的斜率,因此從邏輯上說,若是一些數據點的梯度很大,那它們對於找到最佳分裂方法來講就很重要,由於它們具備較高的偏差。
GOSS保留了全部具備大梯度的數據點,並對梯度小的數據點進行隨機採樣。例如,假設我有50萬行數據,其中1萬行梯度高,剩下的49萬行梯度低,那個人算法就會選擇1萬行+49萬行×x%(隨機)。設x=10,最終算法選出的就是50萬行數據中的5.9萬行。
這裏存在一個基本假設,即梯度較小的數據點具備更低的偏差,並且已經訓練好了
爲了保持相同的數據分佈,在計算分裂增益時,GOSS會爲這些梯度小的數據點引入一個常數乘數。以上就是它能在減小數據點數量和保證決策樹準確性之間取得平衡的方法。
CatBoost
CatBoost在分類變量索引方面具備至關的靈活性,它能夠用在各類統計上的分類特徵和數值特徵的組合將分類值編碼成數字(one_hot_max_size
:若是feature包含的不一樣值的數目超過了指定值,將feature轉化爲float)。
若是你沒有在cat_features
語句中傳遞任何內容,CatBoost會把全部列視爲數值變量。
注:若是在
cat_features
中未提供具備字符串值的列,CatBoost會報錯。此外,具備默認int類型的列在默認狀況下也會被視爲數字,因此你要提早手動定義。
對於分類值大於one_hot_max_size
的那些分類變量,CatBoost也有一種有效的方法。它和均值編碼相似,但能夠防止過擬合:
對輸入樣本從新排序,並生成多個隨機排列;
將label值從浮點或類別轉換爲整型;
用如下公式把全部分類特徵值轉換爲數值,其中CountInClass表示截至當前樣本,label值=1的次數(相一樣本總數);Prior表示平滑因子,它由起始參數肯定;而TotalCount則表明截至當前樣本,全部樣本的總數。
若是轉換爲數學公式,它長這樣:
LightGBM
和CatBoost相似,LightGBM也能夠經過輸入特徵名稱來處理分類特徵。它無需進行獨熱編碼(one-hot coding),而是使用一種特殊的算法直接查找分類特徵的拆分值,最後不只效果類似,並且速度更快。
注:在爲LGBM構造數據集以前,應將分類特徵轉換爲整型數據,即使你用了categorical_feature參數,算法也沒法識別字符串值。
XGBoost
XGBoost沒法單獨處理分類特徵,它是基於CART的,因此只接收數值。在把分類數據提供給算法前,咱們先得執行各類編碼,如標籤編碼、均值編碼、獨熱編碼等。
這三種算法涉及的超參數有不少,這裏咱們只介紹幾個重要的。下表是它們的對比:
我使用的是2015年航班延誤的Kaggle數據集,由於它同時包含分類特徵和數字特徵,並且大約有500萬行數據,不管是從訓練速度上看仍是從模型的準確率上看,它均可以做爲一個很好的性能判斷工具。
我從數據集中抽取10%(50萬行)做爲實驗數據,如下是建模使用的特徵:
MONTH,DAY,DAYOFWEEK:整型數據
AIRLINE和FLIGHT_NUMBER:整型數據
ORIGINAIRPORT和DESTINATIONAIRPORT:字符串
DEPARTURE_TIME:float
ARRIVAL_DELAY:預測目標,航班延遲是否超過10分鐘?
DISTANCE和AIR_TIME:float
XGBoost
Light GBM
CatBoost
在爲CatBoost調參時,我發現它很難爲分類特徵傳遞索引。因此我針對沒傳遞的特徵調整了參數,最後有了兩個模型:一個包含分類特徵,一個不包含。由於onehotmax_size不影響其餘參數,因此我單獨對它作了調整。
結果
如今咱們就能從訓練速度和準確率兩個維度對3種算法進行評價了。
如上表所示,CatBoost在測試集上的準確率高達0.816,同時過擬合程度最低,訓練時長短,預測時間也最少。但它真的戰勝其餘兩種算髮了嗎?很惋惜,沒有。0.816這個準確率的前提是咱們考慮了分類變量,並且單獨調整了onehotmax_size。若是沒有充分利用算法的特性,CatBoost的表現是最差的,準確率只有0.752。
因此咱們能夠得出這樣一個結論:若是數據中存在分類變量,咱們能夠充分利用CatBoost的特性獲得一個更好的訓練結果。
接着就是咱們的數據競賽王者XGBoost。它的表現很穩定,若是忽略以前的數據轉換工做,單從準確率上看它和CatBoost很是接近。可是XGBoost的缺點是太慢了,尤爲是調參過程,簡直使人絕望(我花了6小時擺弄GridSearchCV)。
最後就是Light GBM,這裏我想提一點,就是用cat_features時它的速度和準確率會很是糟糕,我猜想這多是由於這時算法會在分類數據中用某種改良過的均值編碼,以後就過擬合了。若是咱們能像XGBoost同樣操做,它也許能夠在速度秒殺XGBoost的同時達到後者的精度。
綜上所述,這些觀察結果都是對應這個數據集得出的結論,它們可能不適用於其餘數據集。我在文中沒有展現交叉驗證過程,但我確實嘗試了,結果差很少。話雖如此,但有一個結果是千真萬確的:XGBoost確實比其餘兩種算法更慢。