什麼是 XGBoost?如何直觀理解 XGBoost?它為什麼這麼優秀?
我對十五年前第一天工作的情況還記憶猶新。彼時我剛畢業,在一家全球投資銀行做分析師。我打著領帶,試圖記住學到的每一件事。與此同時,在內心深處,我很懷疑自己是否可以勝任這份工作。感受到我的焦慮後,老闆笑著說:
「別擔心,你只需要瞭解迴歸模型就可以了。」
我當初想的是「我知道這個!」。我知道迴歸模型——線性迴歸和 logistic 迴歸都知道。老闆是對的。我在任職期間僅僅構建了基於迴歸的統計模型。我並不是一個人。事實上,當時的迴歸模型在預測分析中獨佔鰲頭。而十五年後的今天,迴歸模型的時代已經結束了。遲暮的女王已經退場,取而代之的是名字時髦、活力滿滿的新女王——XGBoost(Exterme Gradient Boosting,極限梯度提升)。
什麼是 XGBoost?
XGBoost 是基於決策樹的整合機器學習演算法,它以梯度提升(Gradient Boost)為框架。在非結構資料(影像、文字等)的預測問題中,人工神經網路的表現要優於其他演算法或框架。但在處理中小型結構資料或表格資料時,現在普遍認為基於決策樹的演算法是最好的。下圖列出了近年來基於樹的演算法的演變過程:
從決策樹到 XGBoost 演算法的演變。
XGBoost 演算法最初是華盛頓大學的一個研究專案。陳天奇和 Carlos Guestrin 在 SIGKDD 2016 大會上發表的論文《XGBoost: A Scalable Tree Boosting System》在整個機器學習領域引起轟動。自發表以來,該演算法不僅多次贏得 Kaggle 競賽,還應用在多個前沿工業應用中,並推動其發展。許多資料科學家合作參與了 XGBoost 開源專案,GitHub 上的這一專案(https://github.com/dmlc/xgboost/)約有 350 個貢獻者,以及 3600 多條提交。和其他演算法相比,XGBoost 演算法的不同之處有以下幾點:
應用範圍廣泛:該演算法可以解決迴歸、分類、排序以及使用者自定義的預測問題;
可移植性:該演算法可以在 Windows、Linux 和 OS X 上流暢地執行;
語言:支援包括 C++、Python、R、Java、Scala 和 Julia 在內的幾乎所有主流程式語言;
雲整合:支援 AWS、Azure 和 Yarn 叢集,也可以很好地配合 Flink、 Spark 等其他生態系統。
對 XGBoost 的直觀理解
決策樹是易於視覺化、可解釋性相對較強的演算法,但是要建立下一代基於樹的演算法的直觀理解可能就有些棘手了。為了更好地理解基於樹的演算法的演變過程,我對其做了簡單的類比:
假設你是面試官,要面試幾名資歷非常優秀的求職者。基於樹的演算法演變過程的每一步都可以類比為不同版本的面試場景。
決策樹:每一名面試官都有一套自己的面試標準,比如教育水平、工作經驗以及面試表現等。決策樹類似於面試官根據他(她)自己的標準面試求職者。
袋裝法(Bagging):現在面試官不只有一個人,而是一整個面試小組,小組中的每位面試官都有投票權。Bagging(Boostrap Aggregating)就是透過民主投票過程,綜合所有面試官的投票,然後做出最終決定。
隨機森林(Random Forest):這是基於 Bagging 的演算法,但與 Bagging 有明顯區別——它隨機選擇特徵子集。也就是,每位面試官只會隨機選擇一些側面來對求職者進行面試(比如測試程式設計技能的技術面或者是評估非技術技能的行為面試)。
Boosting:這是一種替代方法,每位面試官根據前一位面試官的反饋來調整評估標準。透過部署更動態的評估流程來「提升」面試效率。
梯度提升(Gradient Boosting):這是 Boosting 的特例,這種演算法透過梯度下降演算法來最小化誤差。用面試類比的話,就是戰略諮詢公司用案例面試來剔除那些不符合要求的求職者;
XGBoost:將 XGBoost 視為「打了雞血」的梯度提升(將這種演算法稱為「極限梯度提升」是有原因的!)。這是軟硬體最佳化技術的完美結合,它可以在最短時間內用更少的計算資源得到更好的結果。
為什麼 XGBoost 如此優秀?
XGBoost 和梯度提升機(Gradient Boosting Machine,GBM)都是用梯度下降架構增強弱學習器(一般是 CART)的整合樹方法。但 XGBoost 透過系統最佳化和演算法增強改進了基礎 GBM 框架。
XGBoost 是如何最佳化標準 GBM 演算法的
系統最佳化
並行:XGBoost 用並行的方式實現了序列樹的構建過程。考慮到用於構建基礎學習器的迴圈、列舉樹的葉節點的外部迴圈以及計算特徵的第二個內部迴圈的可互換性,這是完全有可能實現的。由於沒有完整的內部迴圈就無法啟動外部迴圈(兩個迴圈要求的計算資源更多),因此這種巢狀的迴圈限制了並行。為了改善執行時,就要交換迴圈的順序,這透過對所有例項進行全域性掃描來執行初始化以及用並行執行緒排序來實現。這樣的變換抵消了計算中並行所需的開銷,從而提升了演算法效能。
剪枝:從本質上講 GBM 框架內樹分裂的停止標準是貪婪的,這取決於分裂點的負損失。XGBoost 優先使用指定的「max_depth」引數,然後開始後向修剪樹。這種「深度優先」的方法顯著提升了計算效能。
硬體最佳化:XGBoost 演算法可以有效利用硬體資源。這是透過快取感知(cache awareness)實現的,而快取感知則是透過在每個執行緒中分配內部緩衝區來儲存梯度統計資訊實現的。「核外」計算等進一步增強措施則在處理與記憶體不相容的大資料幀時最佳化了可用磁碟空間。
演算法增強:
正則化:用 LASSO(L1)正則化和 Ridge(L2)正則化懲罰更復雜的模型,以防止過擬合。
稀疏性感知(Sparsity Awareness):XGBoost 根據訓練損失自動「學習」最佳缺失值,從而承認輸入的稀疏特徵,還可以更高效地處理資料中不同型別的稀疏模式。
加權分位數略圖(Weighted Quantile Sketch):XGBoost 用分散式加權分位數略圖演算法(https://arxiv.org/pdf/1603.02754.pdf)高效地從加權資料集中找到最佳分裂點。
交叉驗證:該演算法在每次迭代時都使用內建的交叉驗證方法,這樣就無需特地為搜尋程式設計,也不需要每次執行時都指定所需迭代增強的確切數目。
證據在哪裡?
我們用 Scikit-learn 中的「Make_Classification」(https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_classification.html)資料包建立包含 100 萬個資料點的隨機樣本,其中包含 20 個特徵(2 個是資訊性的,2 個是冗餘的)。我們測試了幾種演算法,比如 Logistic 迴歸、隨機森林、標準梯度提升,以及 XGBoost。
使用 SKLearn 中 Make_Classification 資料集的 XGBoost 演算法和其他 ML 演算法。
如上圖所示,和其他演算法相比,結合預測效能和處理時間兩項來看,XGBoost 是最好的。其他嚴格的基準研究(https://github.com/szilard/benchm-ml)也得到了類似的結果。這也難怪 XGBoost 廣泛應用於近期的資料科學競賽了。
「如有疑問,用 XGBoost 就好」——Owe Zhang,Kaggle Avito 上下文廣告點選大賽冠軍。
那麼我們應該一直用 XGBoost 嗎?
無論是機器學習還是生活,沒有免費的午餐都是一條鐵律。作為資料科學家,我們必須要測試所有能處理手頭資料的演算法,才能判斷哪種演算法是最好的。此外,只是選擇正確的演算法還不夠。我們必須針對要處理的資料集調整超引數,從而選擇合適的配置。此外,要選擇合適的演算法還要考慮其他因素,比如計算複雜度、可解釋性以及易於實現性。這是機器學習從科學走向藝術的開始,但說實話,這也正是見證奇蹟的時刻!
原文連結:https://towardsdatascience.com/https-medium-com-vishalmorde-xgboost-algorithm-long-she-may-rein-edd9f99be63d