XGBoost做爲一個很是經常使用的算法,我以爲頗有必要了解一下它的前因後果,因而抽空找了一些資料,主要包括陳天奇大佬的論文以及演講PPT,以及網絡上的一些博客文章,今天在這裏對這些知識點進行整理概括,論文中的一些專業術語儘量保留不翻譯,但會在下面寫出本身的理解與解釋。算法
資料下載:公衆號(SAMshare)回覆"xgb"獲取緩存
在Paper中,做者定義XGBoost:網絡
a scalable machine learning system for tree boosting.多線程
XGBoost爲「Extreme Gradient Boosting」的縮寫,裏面包含了關鍵字'Boosting',意味着它是一個boosting集成算法,因此它的主要思路是將成百上千個樹模型組合起來成爲一個準確率很高的模型,此模型經過不斷迭代生成新的樹。app
XGBoost咱們經常使用於監督學習,即創建一個數據模型,輸入相關特徵從而預測出目標,而這一過程,須要咱們找到訓練數據最好的參數,因此咱們須要定義一個目標函數,一般由訓練損失(traning loss)和正則項(regularization term)組成。機器學習
訓練損失評估了預測模型的效果,例如經常使用的訓練損失指標是均方偏差或是邏輯迴歸的logistic loss。正則項則是控制着模型的複雜度,避免模型不被過分擬合。這兩個互相博弈(tradeoff)的指標保證了模型的預測效果以及簡潔程度。分佈式
翻譯來講,就是它設計並構建了適用於大規模的 end-to-end 的Boosting系統(end-to-end指的是端到端,就是隻關心輸入和輸出,中間過程都不care),並且實現特徵選擇的並行處理,正則使用L2的稀疏感知算法,並且也提出了有效的緩存結構,加大訓練效率函數
另外,其餘博文也有一些總結:學習
XGBoost仍是採用屬於gradient tree boosting algorithms,推導過程和已有的算法理論相似,但這裏有了一些創新,好比正則化學習目標、樣本子採樣、特徵子採樣、近似算法等等。測試
給定一個n X m維的數據集D,經過訓練D,獲得K棵樹,而這K棵樹累加的值做爲咱們的預測值。
其中,
是CART的空間,q表示每一個樹的結構,其能夠將每一個樣本映射到對應的葉節點中,T是樹中葉子節點的個數。
有了上面的預測值,咱們能夠代入loss function,獲得咱們的損失函數:
能夠看出損失函數由兩部分組成,Training Loss和Regularization。
這一節是對損失函數的推導求解,這裏不是採起傳統的優化方法進行優化,而是採用了Additive Training訓練,咱們將Training Loss部分,展開成K棵樹疊加的形式,開始於一個常數,每次增長一個新的函數學習當前的樹,貪婪地利用偏差函數改善當前模型,而這裏創新的點在於對偏差函數進行二階泰勒近似展開。
具體公式推導就不展開了,建議查閱:
XGBoost原理介紹:http://www.javashuo.com/article/p-yxrafazt-b.html
這一節講到了兩種防止過擬合的tricks,Shrinkage和Column Subsampling。
這個是常見的基礎貪心算法,即對全部的特徵進行遍歷處理,這就要求對計算資源要求比較高,由於須要對每一個特徵計算其信息增益,選擇增益最大的做爲分裂點,固然是須要比較多的時間和算力。
顧名思義,近似算法就是可能效果或者原理和Exact Greedy Algorithm差很少的算法,它的原理是根據特徵分佈的百分位數進行採樣,選擇待分裂點,而後,該算法將連續特徵映射到由這些候選點分割的桶中,彙總統計信息並根據彙總的信息找到最佳解決方案,這裏選擇分裂點的方式有global和local:
分佈式加權直方圖算法是XGBoost提出的一種可並行的算法,樹節點在進行分裂時,須要計算特徵的信息增益,該算法用於高效地生成候選分裂點,對於大型的數據集,若是每一個實例具備相等權重時,quantile sketch算法能夠解決,但對於加權數據集來講,則不適用,爲了解決該問題,XGBoost提出了分佈式加權quantile sketch算法。
稀疏感知分裂發現,在現實生活中,特徵每每都是稀疏的,有幾種可能的緣由致使特徵稀疏:
1)presence of missing values in the data;
2)frequent zero entries in the statistics;
3)artifacts of feature engineering such as one-hot encoding
XGBoost以統一的方式處理缺失的狀況,分裂中只選擇沒有缺失的數據去進行節點分支,而後缺失狀況默認指定一個方向,其效率paper裏說了是提高了50倍。
即按列分塊並行化學習,XGBoost會對每一個特徵的值進行排序,使用CSC結構存儲到塊(block)中,訓練過程對特徵分枝點計算採用並行處理,尋找合適的分裂點。因此咱們常說的XGBoost的並行計算指的是否是樹的學習上,而是在特徵上的並行處理。
因此,這裏XGBoost在設計系統的時候,預留額外的空間(Block)賴儲存排序好的數據,這裏的排序,是按照每列的值排序,因此索引在不一樣特徵之間是不同的。
因此,特徵預排序只須要在開始的時候作一次便可,後續能夠重複調用,大大減小了每次排序的耗時,因此也能夠實現並行化學習,計算每一個特徵的信息增益。
即緩存感知訪問,對於有大量數據或者說分佈式系統來講,咱們不可能將全部的數據都放進內存裏面。所以咱們都須要將其放在外存上或者分佈式存儲。可是這有一個問題,這樣作每次都要從外存上讀取數據到內存,這將會是十分耗時的操做。
所以咱們使用預讀取(prefetching)將下一塊將要讀取的數據預先放進內存裏面。其實就是多開一個線程,該線程與訓練的線程獨立並負責數據讀取。此外,還要考慮Block的大小問題。若是咱們設置最大的block來存儲全部樣本在k特徵上的值和梯度的話,cache未必能一次性處理如此多的梯度作統計。若是咱們設置過少block size,這樣不能充分利用的多線程的優點,也就是訓練線程已經訓練完數據,可是prefetching thread還沒把數據放入內存或者cache中。
通過測試,做者發現block size設置爲2^16個examples最好。
由於XGBoost是要設計一個高效使用資源的系統,因此各類機器資源都要用上,除了CPU和內存以外,磁盤空間也能夠利用來處理數據。爲了實現這個功能,咱們能夠將數據分紅多個塊並將每一個塊儲存在磁盤上。
在計算過程當中,使用獨立的線程將Block預提取到主內存緩衝區,這樣子數據計算和磁盤讀取能夠同步進行,但因爲IO很是耗時,因此還有2種技術來改善這種核外計算:
XGBoost原理介紹 http://www.javashuo.com/article/p-yxrafazt-b.html
本文由博客一文多發平臺 OpenWrite 發佈!