XGBoost原理及實戰

概述

XGBoost是boosting算法的其中一種。Boosting算法的思想是將許多弱分類器集成在一起形成一個強分類器。XGBoost是一種提升樹模型,它是將許多樹模型集成在一起,形成一個很強的分類器,所用到的樹模型則是CART迴歸樹模型。

CART

CART算法之前文章已經說過,這裏簡單介紹下:

CART迴歸樹是假設樹的結構爲二叉樹,通過不斷將特徵進行分裂去完成整個樹的構建。比如當前樹結點是基於第j個特徵值進行分裂的,設該特徵值小於​s的樣本劃分爲左子樹,大於s的樣本劃分爲右子樹,即 

其實質就是在該特徵維度上對樣本空間進行劃分,這種劃分是非常複雜度,通常是NP難問題。因此,在決策樹模型中是使用啓發式方法解決特徵劃分問題。

典型CART迴歸樹模型的目標函數爲:

我們結合求解最優的切分特徵j和最優的切分點s,那麼目標函數就轉化爲求解如下式子: 

 

XGBoost算法原理

XGBoost算法思想就是不斷地添加樹,不斷地進行特徵分裂來完成一棵樹的構建。每次添加一個樹,實際上是學習一個新函數,去擬合上次預測的殘差。我們訓練完成時會得到k棵樹 。當我們要預測一個樣本的分數時,根據這個樣本的特徵,在每棵樹中會落到對應的一個葉子節點,每個葉子節點就對應一個分數,最後只需要將每棵樹對應的分數加起來就是該樣本的預測值。如:

注:Wq(x)爲葉子節點q的分數--可以理解爲權重,f(x)爲其中一棵迴歸樹 。

如下圖所示,訓練出了2棵決策樹,小孩的預測分數就是兩棵樹中小孩所落到的結點的分數相加。爺爺的預測分數同理。

 

XGBoost損失函數


XGBoost目標函數定義爲:

目標函數由兩部分構成,第一部分用來衡量預測分數和真實分數的差距,另一部分​則是正則化項。

正則化項同樣包含兩部分,

T表示葉子結點的個數,w表示葉子節點的分數。r可以控制葉子結點的個數,可以制葉子節點的分數不會過大,防止過擬合。

正如第二部分所說,新生成的樹是要擬合上次預測的殘差的,即當生成​t棵樹後,預測分數可以寫成:

同時,可以將目標函數改寫成: 

很明顯,我們接下來就是要去找到一個​ft能夠最小化目標函數。XGBoost的想法是利用其在ft = 0處的泰勒二階展開近似它。即

 

所以,目標函數近似爲:

其中​爲g一階導數,h 爲二階導數:

式子中的g和h是一階和二階梯度。

以上這就是XGboost的特點:通過這種近似,可以自行定義一些損失函數(例如,平方損失,邏輯損失),只需要保證二階可導即可。由於前t-1棵樹的預測分數與​的殘差對目標函數優化不影響[因爲t輪是在之前殘差基礎上進行預測,所以可以看作是常數],可以直接去掉。簡化目標函數爲:

上式是將每個樣本的損失函數值加起來,我們知道,每個樣本都最終會落到一個葉子結點中,所以我們可以將所以同一個葉子結點的樣本重組起來,過程如下:

前兩步i=1 to n 其實是對於每一個樣本來說,進行遍歷

最後一步直接把樣本放在葉子結點的結果中去計算,這樣可以便於進行計算

因此通過上式的改寫,我們可以將目標函數改寫成關於葉子結點分數w的一個一元二次函數,求解最優的​和目標函數值就變得很簡單了。

對於一個固定的結構​q(x) ,我們可以計算葉節點j的最優權重wj:

即對w求導,令其等於0

分裂結點算法在上面的推導中,我們知道了如果我們一棵樹的結構確定了,如何求得每個葉子結點的分數。但我們還沒介紹如何確定樹結構,即每次特徵分裂怎麼尋找最佳特徵,怎麼尋找最佳分裂點。

XGBoost使用了和CART迴歸樹一樣的想法,利用貪心算法,遍歷所有特徵的所有特徵劃分點。具體做法就是分裂後的目標函數值比單子葉子節點的目標函數的增益,同時爲了限制樹生長過深,還加了個閾值,只有當增益大於該閾值才進行分裂。

這個公式通常被用於評估分割候選集(選擇最優分割點),其中前兩項分別是切分後左右子樹的的分支之和,第三項是未切分前該父節點的分數值,最後一項是引入額外的葉節點導致的複雜度。同時可以設置樹的最大深度、當樣本權重和小於設定閾值時停止生長去防止過擬合。

正則化

XGBoost的正則化項爲:

注意:這裏出現了​ r和​\[ \lambda \],這是XGBoost自己定義的,在使用XGBoost時,你可以設定它們的值,顯然,​越大,表示越希望獲得結構簡單的樹,因爲此時對較多葉子節點的樹的懲罰越大。​越大也是越希望獲得結構簡單的樹。

XGBoost的優缺點

XGBoost可以成爲機器學習的大殺器,廣泛用於數據科學競賽和工業界,是因爲它有許多優點:

  1. 使用許多策略去防止過擬合,如:正則化項、Shrinkage and Column Subsampling等。
  2. 目標函數優化利用了損失函數關於待求函數的二階導數。
  3. 支持並行化,這是XGBoost的閃光點,雖然樹與樹之間是串行關係,但是同層級節點可並行。具體的對於某個節點,節點內選擇最佳分裂點,候選分裂點計算增益用多線程並行。訓練速度快。
  4. 添加了對稀疏數據的處理。
  5. 交叉驗證,early stop,當預測結果已經很好的時候可以提前停止建樹,加快訓練速度。
  6. 支持設置樣本權重,該權重體現在一階導數​g和二階導數h​,通過調整權重可以去更加關注一些樣本。

但是也存在缺點:

  1. 算法採用貪心策略,較爲耗時。--很多情況下可以對比LightGBM

應用場景

常用的分類問題的場景都可以引入XGBoost作爲分類器,而且基本都是最優結果。在推薦領域中,我們常常把推薦問題映射成一個分類問題。通過收集用戶的打分數據進行分析並推斷出用戶行爲模型,進而對某個產品進行預測打分。一般情況下通過將物品屬性和用戶屬性的各個特徵作爲輸入,將打分作爲類別轉換爲一個分類問題甚至是預測“next item”問題。這裏面,輸入數據假設爲<u,i> 的二元組,每個組內包括用戶u的特徵向量和物品i的特徵向量,我們預測該用戶是否點擊了該物品,這樣就將推薦問題轉換爲了分類問題。在業界,一般情況下處理這種分類問題有兩種途徑,一爲LR+XGBoost,二爲End-to-End模型;其中第一種因爲部署簡單,效果好而被廣泛使用,但面臨特徵工程的問題,第二種模型設計部署非常複雜,但是效果往往會更優化一點。作爲一般推薦系統而言,使用XGBoost作爲推薦模型的基礎算法或CTR預估問題的基礎算法是一個比較合理的方式。

 

python實戰

樣本還是之前一直用的糖尿病數據集

數據處理

#dmatrix 格式 在xgboost當中運行速度更快,性能更好。
dtrain = xgb.DMatrix(data,label)
dtest = xgb.DMatrix(X_test,y_test)

參數設置 

Xgboost參數

'booster':'gbtree',
'objective': 'multi:softmax', 多分類的問題
'num_class':10, 類別數,與 multisoftmax 並用
'gamma':損失下降多少才進行分裂
'max_depth':12, 構建樹的深度,越大越容易過擬合
'lambda':2, 控制模型複雜度的權重值的L2正則化項參數,參數越大,模型越不容易過擬合。
'subsample':0.7, 隨機採樣訓練樣本
'colsample_bytree':0.7, 生成樹時進行的列採樣
'min_child_weight':3, 孩子節點中最小的樣本權重和。如果一個葉子節點的樣本權重和小於min_child_weight則拆分過程結束
'silent':0 ,設置成1則沒有運行信息輸出,最好是設置爲0.
'eta': 0.007, 如同學習率
'seed':1000,
'nthread':7, cpu 線程數

 這裏我們只爲測試代碼,不做調試

bst_cv = xgb.cv(xgb_params, dtrain, num_boost_round=50, nfold=3, seed=0, 
                 maximize=False, early_stopping_rounds=10)

cv驗證,可以直接做圖查看下結果

plt.figure()
bst_cv1[['train-rmse-mean', 'test-rmse-mean']].plot()

訓練

bst = xgb.train(xgb_params, dtrain, 100, evals=[(dtrain,'train'), (dtest,'test')])

查看下預測結果

preds = bst.predict(dtest)
auc = metrics.roc_auc_score(y_test, preds)

out:

0.8334398159979555

完整代碼可以查看我的GitHub:

https://github.com/Andyszl/Recommendation_algorithm/blob/master/Xgboost.py

 

參考:

https://zhuanlan.zhihu.com/p/74427646

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章