XGBoost(eXtreme Gradient Boosting)其核心是對決策樹(Decision Tree)的加強(Boosting)方法,屬於集成學習(Ensemble Learning)。
下文分別對決策樹、決策樹集成以及Xgboost進行介紹。
1、決策樹 Decision Tree
決策樹是一種常見的監督學習方法,能夠用於處理分類和迴歸問題。
分類問題(離散值):西瓜甜不甜?
迴歸問題(連續值):房價多少?複製代碼
顧名思義就是構建一個樹形的決策過程。樹中的每一個節點即挑選特定特徵對樣本進行決策。
特徵樹的構建主要分爲三個步驟:
特徵選擇、決策樹構建、剪枝。
其中根據特徵選擇的方式不一樣,分爲ID三、C4.五、CART三類主要算法。
ID3基於信息增益進行特徵選擇:
分爲訓練集數據在通過特徵A前/後的信息熵。
經過選取特徵A最大化信息增益:
可是因爲特徵的取值不均衡的問題(好比性別只有男女,年齡能夠分不少類),ID3算法更傾向於選擇取值更多的特徵。
CART(Classification And Regression Tree)基於基尼係數進行特徵選擇,在分類問題中:
經過將計算熵值(對數運算)轉變爲計算基尼係數(平方運算)大大下降了運算複雜度。
對於迴歸樹而言,CART能夠處理迴歸樹問題,其優化目標以下:
即經過特徵j和切分點s將數據集切分爲兩個集合, 並最小化兩個集合中各自樣本的方差(c1,c2分別是集合樣本的均值)。
總的來講,決策樹是基於特徵進行if-then的決策過程,高效、易於理解。可是對訓練樣本嚴重依賴,容易生成複雜的樹結構,形成過擬合(overfitting)等問題。並且若是要學習獲得一棵最優的決策樹被認爲是NP-Complete問題。實際中的決策樹是基於啓發式的貪心算法創建的,這種算法不能保證創建全局最優的決策樹。
2、決策樹集成 Tree Ensemble
集成學習(ensemble learning)經過構建並結合多個學習器來完成學習任務,這裏主要關注Bagging和Boosting兩類。
2.1 Bagging
Bagging (bootstrap aggregating) 是基於Bootstraping重採樣方法(有放回的採樣),獨立訓練產生k個模型,並綜合k個模型的輸出獲得最終結果(分類問題能夠採用投票方式,迴歸問題能夠採用均值)。Bootstraping一般可以包含63.2%的數據樣本
。它能夠並行執行,並經過這種方式避免模型對於訓練數據過於敏感,減小模型的方差。
Bagging與決策樹的結合就獲得了隨機森林(Random Forest),與Bagging方法惟一的不一樣在於Random Forest在特徵選擇前,使用了特徵採樣(通常使用
個特徵),減小了強分類屬性對模型的影響,使得不一樣模型更爲獨立。
2.2 Boosting
Boosting方法中數據集是不變的而在改變樣本的權重,使得後續模型更關注與先前模型錯分的樣本,須要串行執行。具體而言能夠分爲以下幾類:
AdaBoosting(Adaptive Boosting),在Boosting的基礎上AdaBoosting爲每輪迭代過程當中基於加權後樣本的誤率賦予每一個模型對應權值。模型權重與迭代過程當中樣本權重的更新方法以下:
Gradient Boosting 通常用於迴歸樹,採用上輪模型預測值與真實值之間的殘差做爲下一輪的輸入
表示第i個樣本第m輪的殘差,
分別爲真實值和預測值。
GBDT(Gradient Boosting Decision Tree), 對於下一輪的輸入(殘差),根據不一樣的損失函數提供了不一樣的計算方法,
。當損失函數爲平方差時,殘差與GB中一致。經過加入了學習率的概念,能夠調整對於錯分數據的關注。
Xgboost本文主角,這裏與GBDT先作一個比較,後續作詳細說明:
1. 將樹模型的複雜度加入到正則項中,來避免過擬合,所以泛化性能會優於GBDT。
2. 損失函數是用泰勒展開式展開的,同時用到了一階導和二階導,能夠加快優化速度。
3. 和GBDT只支持CART做爲基分類器以外,還支持線性分類器,在使用線性分類器的時候可使用L1,L2正則化。
4. 引進了特徵子採樣,像RandomForest那樣,這種方法既能下降過擬合,還能減小計算。
5. 在尋找最佳分割點時,考慮到傳統的貪心算法效率較低,實現了一種近似貪心算法,用來加速和減少內存消耗,除此以外還考慮了稀疏數據集和缺失值的處理,對於特徵的值有缺失的樣本,XGBoost依然能自動找到其要分裂的方向。
6. XGBoost支持並行處理,XGBoost的並行不是在模型上的並行,而是在特徵上的並行,將特徵列排序後以block的形式存儲在內存中,在後面的迭代中重複使用這個結構。這個block也使得並行化成爲了可能,其次在進行節點分裂時,計算每一個特徵的增益,最終選擇增益最大的那個特徵去作分割,那麼各個特徵的增益計算就能夠開多線程進行。算法
3、Xgboost
與論文對應,這裏分爲三個部分對Xgboost進行介紹:Xgboost模型、分割點的查找、算法並行實現。bootstrap
3.1.3 Shrinkage and Column Subsampling
Shrinkage(收縮)即能和GBDT同樣設置學習率,削減每棵樹的影響,讓後面有更大的學習空間。實際應用中,通常把學習率設置得小一點,而後迭代次數設置得大一點。
Column Subsampling(列抽樣)即Random Forest中的特徵抽樣方法,使得每棵樹可以儘可能獨立。
3.2 分割點的查找 Split Finding
爲了找到特徵的最優切分點,須要遍歷特徵全部的取值,並獲得全部可能的切分點。而後帶入目標函數進行計算,並將最優的目標函數值對應的切分點,做爲特徵的切分點。可是因爲迴歸問題中,特徵是連續的存在不少候選切分點,因此找到最優切分點須要耗費大量的時間和內存。
3.2.1 Approximate Algorithm
Xgboost採用了一種近似作法,對排序後的特徵進行分段,只在分段和分段間造成候選的切分點,大大減小了候選分割點的個數。其算法和效果以下圖所示
分割點的近似查找方法,分爲全局和局部兩種api
最優分割和近似分割比較。eps = epsilon,表示按照eps比例對數據集進行劃分
這裏一個重要的問題是按照何種標準生成候選分割點,Xgboost中並非簡單地等分切割,而是根據二階導數進行加權切割。。緩存
3.2.2 Sparsity-aware Split Finding
對於數據稀疏的狀況,好比:1. 數據缺失值;2. 大量的0值; 3. 進行了One-hot 編碼。Xgboost提供了對應的算法給與稀疏的數據一個默認值。其方法核心在於將缺失的樣本所有劃分在節點的左側或是右側,並選擇其中增益最大的一種劃分方法做爲默認劃分。bash
3.3 系統設計 System Design
3.3.1 Column Block for Parallel Learning
建樹過程當中最大的耗時在於對樣本的排序,爲了下降排序時間,採用Block結構對排序信息進行存儲:
能夠看出,只需在建樹前排序一次,後面節點分裂時能夠直接根據索引獲得梯度信息。多線程
在Exact greedy算法中,將整個數據集存放在一個Block中。這樣,複雜度從原來的app
這樣,Exact greedy算法就省去了每一步中的排序開銷。dom
在近似算法中,使用多個Block,每一個Block對應原來數據的子集。不一樣的Block能夠在不一樣的機器上計算。該方法對Local策略尤爲有效,由於Local策略每次分支都從新生成候選切分點。函數
Block結構還有其它好處,數據按列存儲,能夠同時訪問全部的列,很容易實現並行的尋找分裂點算法。此外也能夠方便實現以後要講的out-of score計算。但缺點是空間消耗大了一倍。
3.3.2 Cache-aware Access
使用Block結構的一個缺點是取梯度的時候,是經過索引來獲取的,而這些梯度的獲取順序是按照特徵的大小順序的。這將致使非連續的內存訪問,可能使得CPU cache緩存命中率低,從而影響算法效率。性能
所以,對於exact greedy算法中, 使用緩存預取。具體來講,對每一個線程分配一個連續的buffer,讀取梯度信息並存入Buffer中(這樣就實現了非連續到連續的轉化),而後再統計梯度信息。該方式在訓練樣本數大的時候特別有用,見下圖:
在approximate 算法中,對Block的大小進行了合理的設置。定義Block的大小爲Block中最多的樣本數。設置合適的大小是很重要的,設置過大則容易致使命中率低,太小則容易致使並行化效率不高。通過實驗,發現2^16比較好。
3.3.3 Blocks for Out-of-core Computation
當數據量太大不能所有放入主內存的時候,爲了使得out-of-core計算稱爲可能,將數據劃分爲多個Block並存放在磁盤上。
計算的時候,使用獨立的線程預先將Block放入主內存,所以能夠在計算的同時讀取磁盤
Block壓縮,貌似採用的是近些年性能出色的LZ4 壓縮算法,按列進行壓縮,讀取的時候用另外的線程解壓。對於行索引,只保存第一個索引值,而後用16位的整數保存與該block第一個索引的差值。
Block Sharding, 將數據劃分到不一樣硬盤上,提升磁盤吞吐率