xgboost: 速度快效果好的boosting模型


轉自:http://cos.name/2015/03/xgboost/

本文作者:何通,SupStat Inc(總部在紐約,中國分部為北京數博思達信息科技有限公司)數據科學家,加拿大Simon Fraser University計算機學院研究生,研究興趣為數據挖掘和生物信息學。

主頁:https://github.com/hetong007

引言

在數據分析的過程中,我們經常需要對數據建模並做預測。在眾多的選擇中,randomForestgbmglmnet是三個尤其流行的R包,它們在Kaggle的各大數據挖掘競賽中的出現頻率獨占鰲頭,被坊間人稱為R數據挖掘包中的三駕馬車。根據我的個人經驗,gbm包比同樣是使用樹模型的randomForest包占用的內存更少,同時訓練速度較快,尤其受到大家的喜愛。在python的機器學習庫sklearn里也有GradientBoostingClassifier的存在。

Boosting分類器屬於集成學習模型,它基本思想是把成百上千個分類准確率較低的樹模型組合起來,成為一個准確率很高的模型。這個模型會不斷地迭代,每次迭代就生成一顆新的樹。對於如何在每一步生成合理的樹,大家提出了很多的方法,我們這里簡要介紹由Friedman提出的Gradient Boosting Machine。它在生成每一棵樹的時候采用梯度下降的思想,以之前生成的所有樹為基礎,向着最小化給定目標函數的方向多走一步。在合理的參數設置下,我們往往要生成一定數量的樹才能達到令人滿意的准確率。在數據集較大較復雜的時候,我們可能需要幾千次迭代運算,如果生成一個樹模型需要幾秒鍾,那么這么多迭代的運算耗時,應該能讓你專心地想靜靜……

Rocket

現在,我們希望能通過xgboost工具更好地解決這個問題。xgboost的全稱是eXtreme Gradient Boosting。正如其名,它是Gradient Boosting Machine的一個c++實現,作者為正在華盛頓大學研究機器學習的大牛陳天奇。他在研究中深感自己受制於現有庫的計算速度和精度,因此在一年前開始着手搭建xgboost項目,並在去年夏天逐漸成型。xgboost最大的特點在於,它能夠自動利用CPU的多線程進行並行,同時在算法上加以改進提高了精度。它的處女秀是Kaggle的希格斯子信號識別競賽,因為出眾的效率與較高的預測准確度在比賽論壇中引起了參賽選手的廣泛關注,在1700多支隊伍的激烈競爭中占有一席之地。隨着它在Kaggle社區知名度的提高,最近也有隊伍借助xgboost在比賽中奪得第一

為了方便大家使用,陳天奇將xgboost封裝成了python庫。我有幸和他合作,制作了xgboost工具的R語言接口,並將其提交到了CRAN上。也有用戶將其封裝成了julia庫。python和R接口的功能一直在不斷更新,大家可以通過下文了解大致的功能,然后選擇自己最熟悉的語言進行學習。

 

功能介紹

一、基礎功能

首先,我們從github上安裝這個包:

devtools::install_github('dmlc/xgboost',subdir='R-package')

動手時間到!第一步,運行下面的代碼載入樣例數據:

require(xgboost) data(agaricus.train, package='xgboost') data(agaricus.test, package='xgboost') train <- agaricus.train test <- agaricus.test 

這份數據需要我們通過一些蘑菇的若干屬性判斷這個品種是否有毒。數據以1或0來標記某個屬性存在與否,所以樣例數據為稀疏矩陣類型:

> class(train$data) [1] "dgCMatrix" attr(,"package") [1] "Matrix"

不用擔心,xgboost支持稀疏矩陣作為輸入。下面就是訓練模型的命令

> bst <- xgboost(data = train$data, label = train$label, max.depth = 2, eta = 1, + nround = 2, objective = "binary:logistic") [0] train-error:0.046522 [1] train-error:0.022263 

我們迭代了兩次,可以看到函數輸出了每一次迭代模型的誤差信息。這里的數據是稀疏矩陣,當然也支持普通的稠密矩陣。如果數據文件太大不希望讀進R中,我們也可以通過設置參數data = 'path_to_file'使其直接從硬盤讀取數據並分析。目前支持直接從硬盤讀取libsvm格式的文件。

做預測只需要一句話:

pred <- predict(bst, test$data)

做交叉驗證的函數參數與訓練函數基本一致,只需要在原有參數的基礎上設置nfold

> cv.res <- xgb.cv(data = train$data, label = train$label, max.depth = 2, + eta = 1, nround = 2, objective = "binary:logistic", + nfold = 5) [0] train-error:0.046522+0.001102 test-error:0.046523+0.004410 [1] train-error:0.022264+0.000864 test-error:0.022266+0.003450 > cv.res train.error.mean train.error.std test.error.mean test.error.std 1: 0.046522 0.001102 0.046523 0.004410 2: 0.022264 0.000864 0.022266 0.003450

交叉驗證的函數會返回一個data.table類型的結果,方便我們監控訓練集和測試集上的表現,從而確定最優的迭代步數。

二、高速准確

上面的幾行代碼只是一個入門,使用的樣例數據沒法表現出xgboost高效准確的能力。xgboost通過如下的優化使得效率大幅提高:

  1. xgboost借助OpenMP,能自動利用單機CPU的多核進行並行計算。需要注意的是,Mac上的Clang對OpenMP的支持較差,所以默認情況下只能單核運行。
  2. xgboost自定義了一個數據矩陣類DMatrix,會在訓練開始時進行一遍預處理,從而提高之后每次迭代的效率。

在盡量保證所有參數都一致的情況下,我們使用希格斯子競賽的數據做了對照實驗。

MODEL AND PARAMETER GBM XGBOOST
1 thread 2 threads 4 threads 8 threads
Time (in secs) 761.48 450.22 102.41 44.18 34.04

以上實驗使用的CPU是i7-4700MQ。python的sklearn速度與gbm相仿。如果想要自己對這個結果進行測試,可以在比賽的官方網站下載數據,並參考這份demo中的代碼。

除了明顯的速度提升外,xgboost在比賽中的效果也非常好。在這個競賽初期,大家驚訝地發現R和python中的gbm竟然難以突破組織者預設的benchmark。而xgboost橫空出世,用不到一分鍾的訓練時間便打入當時的top 10,引起了大家的興趣與關注。准確度提升的主要原因在於,xgboost的模型和傳統的GBDT相比加入了對於模型復雜度的控制以及后期的剪枝處理,使得學習出來的模型更加不容易過擬合。更多算法上的細節可以參考這份陳天奇給出的介紹性講義

三、進階特征

除了速度快精度高,xgboost還有一些很有用的進階特性。下面的“demo”鏈接對應着相應功能的簡單樣例代碼。

  1. 只要能夠求出目標函數的梯度和Hessian矩陣,用戶就可以自定義訓練模型時的目標函數。demo
  2. 允許用戶在交叉驗證時自定義誤差衡量方法,例如回歸中使用RMSE還是RMSLE,分類中使用AUC,分類錯誤率或是F1-score。甚至是在希格斯子比賽中的“奇葩”衡量標准AMSdemo
  3. 交叉驗證時可以返回模型在每一折作為預測集時的預測結果,方便構建ensemble模型。demo
  4. 允許用戶先迭代1000次,查看此時模型的預測效果,然后繼續迭代1000次,最后模型等價於一次性迭代2000次。demo
  5. 可以知道每棵樹將樣本分類到哪片葉子上,facebook介紹過如何利用這個信息提高模型的表現。demo
  6. 可以計算變量重要性並畫出樹狀圖。demo
  7. 可以選擇使用線性模型替代樹模型,從而得到帶L1+L2懲罰的線性回歸或者logistic回歸。demo

這些豐富的功能來源於對日常使用場景的總結,數據挖掘比賽需求以及許多用戶給出的精彩建議。

四、未來計划

現在,機器學習工具在實用中會不可避免地遇到“單機性能不夠”的問題。目前,xgboost的多機分布式版本正在開發當中。基礎設施搭建完成之日,便是新一輪R包開始設計與升級之時。

結語

我為xgboost制作R接口的目的就是希望引進好的工具,讓大家使用R的時候心情更愉悅。總結下來,xgboost的特點有三個:速度快,效果好,功能多,希望它能受到大家的喜愛,成為一駕新的馬車。

xgboost功能較多,參數設置比較繁雜,希望在上手之后有更全面了解的讀者可以參考項目wiki。歡迎大家多多交流,在項目issue區提出疑問與建議。我們也邀請有興趣的讀者提交代碼完善功能,讓xgboost成為更好用的工具。

另外,在使用github開發的過程中,我深切地感受到了協作寫代碼帶來的變化。一群人在一起的時候,可以寫出更有效率的代碼,在豐富的使用場景中發現新的需求,在極端情況發現隱藏很深的bug,甚至在主代碼手拖延症較為忙碌的時候有人挺身而出拿下一片issue。這樣的氛圍,能讓一個語言社區的交流豐富起來,從而充滿生命力地活躍下去。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM