XGBoost(eXtreme Gradient Boosting)其核心是對決策樹(Decision Tree)的增強(Boosting)方法,屬於整合學習(Ensemble Learning)。下文分別對決策樹、決策樹整合以及Xgboost進行介紹。一、決策樹 Decision Tree
決策樹是一種常見的監督學習方法,可以用於處理分類和迴歸問題。分類問題(離散值):
西瓜甜不甜?
迴歸問題(連續值):房價多少?
顧名思義就是構建一個樹形的決策過程。樹中的每個節點即挑選特定特徵對樣本進行決策。特徵樹的構建主要分為三個步驟:特徵選擇、決策樹構建、剪枝。其中根據特徵選擇的方式不同,分為ID3、C4.5、CART三類主要演算法。分為訓練集資料在經過特徵A前/後的資訊熵。透過選取特徵A最大化資訊增益:但是由於特徵的取值不均衡的問題(比如性別只有男女,年齡可以分很多類),ID3演算法更傾向於選擇取值更多的特徵。CART(Classification And Regression Tree)基於基尼係數進行特徵選擇,在分類問題中:透過將計算熵值(對數運算)轉變為計算基尼係數(平方運算)大大降低了運算複雜度。對於迴歸樹而言,CART可以處理迴歸樹問題,其最佳化目標如下:即透過特徵j和切分點s將資料集切分為兩個集合, 並最小化兩個集合中各自樣本的方差(c1,c2分別是集合樣本的均值)。總的來說,決策樹是基於特徵進行if-then的決策過程,高效、易於理解。但是對訓練樣本嚴重依賴,容易生成複雜的樹結構,造成過擬合(overfitting)等問題。而且如果要學習得到一棵最優的決策樹被認為是NP-Complete問題。實際中的決策樹是基於啟發式的貪心演算法建立的,這種演算法不能保證建立全域性最優的決策樹。二、決策樹整合 Tree Ensemble
整合學習(ensemble learning)透過構建並結合多個學習器來完成學習任務,這裡主要關注Bagging和Boosting兩類。Bagging (bootstrap aggregating) 是基於Bootstraping重取樣方法(有放回的取樣),獨立訓練產生k個模型,並綜合k個模型的輸出得到最終結果(分類問題可以採用投票方式,迴歸問題可以採用均值)。Bootstraping通常能夠包含63.2%的資料樣本 。它可以並行執行,並透過這種方式避免模型對於訓練資料過於敏感,減少模型的方差。Bagging與決策樹的結合就得到了隨機森林(Random Forest),與Bagging方法唯一的不同在於Random Forest在特徵選擇前,使用了特徵取樣(一般使用個特徵),減少了強分類屬性對模型的影響,使得不同模型更為獨立。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也使得並行化成為了可能,其次在進行節點分裂時,計算每個特徵的增益,最終選擇增益最大的那個特徵去做分割,那麼各個特徵的增益計算就可以開多執行緒進行。
三、Xgboost
與論文對應,這裡分為三個部分對Xgboost進行介紹:Xgboost模型、分割點的查詢、演算法並行實現。
3.1.3 Shrinkage and Column Subsampling
Shrinkage(收縮)即能和GBDT一樣設定學習率,削減每棵樹的影響,讓後面有更大的學習空間。實際應用中,一般把學習率設定得小一點,然後迭代次數設定得大一點。Column Subsampling(列抽樣)即Random Forest中的特徵抽樣方法,使得每棵樹能夠儘量獨立。為了找到特徵的最優切分點,需要遍歷特徵所有的取值,並得到所有可能的切分點。然後帶入目標函式進行計算,並將最優的目標函式值對應的切分點,作為特徵的切分點。但是由於迴歸問題中,特徵是連續的存在很多候選切分點,所以找到最優切分點需要耗費大量的時間和記憶體。3.2.1 Approximate AlgorithmXgboost採用了一種近似做法,對排序後的特徵進行分段,只在分段和分段間形成候選的切分點,大大減少了候選分割點的個數。其演算法和效果如下圖所示分割點的近似查詢方法,分為全域性和區域性兩種
最優分割和近似分割比較。eps = epsilon,表示按照eps比例對資料集進行劃分這裡一個重要的問題是按照何種標準生成候選分割點,Xgboost中並不是簡單地等分切割,而是根據二階導數進行加權切割。。
3.2.2 Sparsity-aware Split Finding
對於資料稀疏的情況,比如:1. 資料缺失值;2. 大量的0值; 3. 進行了One-hot 編碼。Xgboost提供了對應的演算法給與稀疏的資料一個預設值。其方法核心在於將缺失的樣本全部劃分在節點的左側或是右側,並選擇其中增益最大的一種劃分方法作為預設劃分。
3.3.1 Column Block for Parallel Learning 建樹過程中最大的耗時在於對樣本的排序,為了降低排序時間,採用Block結構對排序資訊進行儲存:- Block 中特徵還需儲存指向樣本的索引,這樣才能根據特徵的值來取梯度。
可以看出,只需在建樹前排序一次,後面節點分裂時可以直接根據索引得到梯度資訊。
在Exact greedy演算法中,將整個資料集存放在一個Block中。這樣,複雜度從原來的
這樣,Exact greedy演算法就省去了每一步中的排序開銷。
在近似演算法中,使用多個Block,每個Block對應原來資料的子集。不同的Block可以在不同的機器上計算。該方法對Local策略尤其有效,因為Local策略每次分支都重新生成候選切分點。
Block結構還有其它好處,資料按列儲存,可以同時訪問所有的列,很容易實現並行的尋找分裂點演算法。此外也可以方便實現之後要講的out-of score計算。但缺點是空間消耗大了一倍。使用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, 將資料劃分到不同硬碟上,提高磁碟吞吐率