XGBoost入门及实战
kaggle比賽必備算法XGBoost入門(mén)及實(shí)戰(zhàn)
xgboost一直在kaggle競(jìng)賽江湖里被傳為神器,它在對(duì)結(jié)構(gòu)化數(shù)據(jù)的應(yīng)用占據(jù)主導(dǎo)地位,是目前開(kāi)源的最快最好的工具包,與常見(jiàn)的工具包算法相比速度提高了10倍以上!
XGBoost is an implementation of gradient boosted decision trees (GBDT) designed for speed and performance.
xgboost 是對(duì)梯度增強(qiáng)決策樹(shù)(GBDT)的一種實(shí)現(xiàn),具有更高的性能以及速度,既可以用于分類(lèi)也可以用于回歸問(wèn)題中。本文將盡量用通俗易懂的方式進(jìn)行介紹并給出實(shí)戰(zhàn)案例。
1.什么是XGBoost?
xgboost 是 eXtreme?Gradient?Boosting的簡(jiǎn)寫(xiě)。
The name xgboost, though, actually refers to the engineering goal to push the limit of computations resources for boosted tree algorithms. Which is the reason why many people use xgboost.
以上是xgboost作者陳天奇在Quora(類(lèi)似國(guó)內(nèi)的知乎)上對(duì)名字的解釋。
xgboost是一個(gè)軟件包,可以通過(guò)各種API接口訪(fǎng)問(wèn)使用:
- Command Line Interface (CLI).命令行
- C++
- Java
- R
- python 和 scikit-learn
- Julia
- Scala
xgboost 的底層實(shí)現(xiàn)在我看來(lái)還是比較復(fù)雜的,想深入理解可以查看陳博士的Paper (XGBoost: A Scalable Tree Boosting System)?,它針對(duì)傳統(tǒng)GBDT算法做了很多細(xì)節(jié)改進(jìn),包括損失函數(shù)、正則化、稀疏感知算法、并行化算法設(shè)計(jì)等等。
Szilard Pafka 數(shù)據(jù)科學(xué)家做了詳細(xì)的性能對(duì)比,并發(fā)表的文章進(jìn)行解釋說(shuō)明(githup:https://github.com/szilard/benchm-ml)?以下是 XGBoost 與其它 gradient boosting 和 bagged decision trees 實(shí)現(xiàn)的效果比較,可以看出它比 R, Python,Spark,H2O 中的基準(zhǔn)配置要更快。
2.XGBoost的特性
說(shuō)到Xgboost,不得不先從GBDT(Gradient Boosting Decision Tree)說(shuō)起。因?yàn)閤gboost本質(zhì)上還是一個(gè)GBDT,但是力爭(zhēng)把速度和效率發(fā)揮到極致,所以叫X (Extreme) GBoosted,兩者都是boosting方法。
Gradient Boosting 是 boosting 的其中一種方法,所謂 Boosting ,就是將弱分離器 f_i(x) 組合起來(lái)形成強(qiáng)分類(lèi)器 F(x) 的一種方法。
那什么是GBDT??我們看一張圖:
GBDT的原理很簡(jiǎn)單,我們反復(fù)循環(huán)構(gòu)建新的模型并將它們組合成一個(gè)集成模型的,從初始Naive模型開(kāi)始,我們從計(jì)算數(shù)據(jù)集中每個(gè)觀(guān)測(cè)的誤差,然后下一個(gè)樹(shù)去擬合誤差函數(shù)對(duì)預(yù)測(cè)值的殘差(殘差就是預(yù)測(cè)值與真實(shí)值之間的誤差),最終這樣多個(gè)學(xué)習(xí)器相加在一起用來(lái)進(jìn)行最終預(yù)測(cè),準(zhǔn)確率就會(huì)比單獨(dú)的一個(gè)要高。
之所以稱(chēng)為 Gradient,是因?yàn)樵谔砑有履P蜁r(shí)使用了梯度下降算法來(lái)最小化的損失。
如圖所示:Y = Y1 + Y2 + Y3。
Parallelization并行處理
XGBoost工具支持并行處理。Boosting不是一種串行的結(jié)構(gòu)嗎?怎么并行的?注意XGBoost的并行不是 tree 粒度的并行,XGBoost 也是一次迭代完才能進(jìn)行下一次迭代的。
XGBoost的并行是在特征粒度上的,決策樹(shù)的學(xué)習(xí)最耗時(shí)的一個(gè)步驟就是對(duì)特征的值進(jìn)行排序,XGBoost在訓(xùn)練之前,預(yù)先對(duì)數(shù)據(jù)進(jìn)行了排序,然后保存為block結(jié)構(gòu),后面的迭代中重復(fù)地使用這個(gè)結(jié)構(gòu),大大減小計(jì)算量。這個(gè)block結(jié)構(gòu)也使得并行成為了可能,在進(jìn)行節(jié)點(diǎn)的分裂時(shí),需要計(jì)算每個(gè)特征的增益,最終選增益最大的那個(gè)特征去做分裂,那么各個(gè)特征的增益計(jì)算就可以開(kāi)多線(xiàn)程進(jìn)行。
正則化
XGBoost 在代價(jià)函數(shù)里加入了正則項(xiàng),用于控制模型的復(fù)雜度。正則項(xiàng)里包含了樹(shù)的葉子節(jié)點(diǎn)個(gè)數(shù)、每個(gè)葉子節(jié)點(diǎn)上輸出的 score 的L2模的平方和。從Bias-variance tradeoff 角度來(lái)講,正則項(xiàng)降低了模型的 variance,使學(xué)習(xí)出來(lái)的模型更加簡(jiǎn)單,防止過(guò)擬合,這也是xgboost優(yōu)于傳統(tǒng)GBDT的一個(gè)特性。
缺失值處理
對(duì)于特征的值有缺失的樣本,xgboost可以自動(dòng)學(xué)習(xí)出它的分裂方向。
損失函數(shù)
傳統(tǒng)GBDT在優(yōu)化時(shí)只用到一階導(dǎo)數(shù)信息,xgboost則對(duì)代價(jià)函數(shù)進(jìn)行了二階泰勒展開(kāi),同時(shí)用到了一階和二階導(dǎo)數(shù)。
分布式計(jì)算
XGBoost is an optimized distributed gradient boosting library designed to be highly efficient, flexible and portable. It implements machine learning algorithms under the Gradient Boosting framework. XGBoost provides a parallel tree boosting (also known as GBDT, GBM) that solve many data science problems in a fast and accurate way.
3.實(shí)戰(zhàn)示例
官方指導(dǎo)文檔:
https://xgboost.readthedocs.io/en/latest/index.html
github 示例文檔:
https://github.com/dmlc/xgboost/tree/master/demo/guide-python
本文將繼續(xù)使用kaggle競(jìng)賽平臺(tái)上的房?jī)r(jià)預(yù)測(cè)的數(shù)據(jù),具體數(shù)據(jù)請(qǐng)移步kaggle實(shí)戰(zhàn)之房?jī)r(jià)預(yù)測(cè),了解一下?
準(zhǔn)備數(shù)據(jù)
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import Imputer data = pd.read_csv('../input/train.csv') data.dropna(axis=0, subset=['SalePrice'], inplace=True) y = data.SalePrice X = data.drop(['SalePrice'], axis=1).select_dtypes(exclude=['object']) train_X, test_X, train_y, test_y = train_test_split(X.as_matrix(), y.as_matrix(), test_size=0.25) my_imputer = Imputer() train_X = my_imputer.fit_transform(train_X) test_X = my_imputer.transform(test_X)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
構(gòu)建模型
#引入xgboost from xgboost import XGBRegressor #xgboost 有封裝好的分類(lèi)器和回歸器,可以直接用XGBRegressor建立模型 my_model = XGBRegressor() # Add silent=True to avoid printing out updates with each cycle my_model.fit(train_X, train_y, verbose=False)- 1
- 2
- 3
- 4
- 5
- 6
評(píng)估及預(yù)測(cè)
# make predictions predictions = my_model.predict(test_X) from sklearn.metrics import mean_absolute_error print("Mean Absolute Error : " + str(mean_absolute_error(predictions, test_y)))- 1
- 2
- 3
- 4
- 5
模型調(diào)參
xgboost模型參數(shù)有幾十種,以上我們只是使用的默認(rèn)的參數(shù)進(jìn)行訓(xùn)練預(yù)測(cè),參數(shù)詳解請(qǐng)參照:
Parameters (official guide)
XGBoost有幾個(gè)參數(shù)會(huì)顯著影響模型的準(zhǔn)確性和訓(xùn)練速度,你應(yīng)該需要特別關(guān)注,并適當(dāng)?shù)倪M(jìn)行調(diào)參:
#1. n_estimators
n_estimators指定通過(guò)建模周期的次數(shù),可以理解成迭代次數(shù),值太大會(huì)導(dǎo)致過(guò)度擬合,這是對(duì)訓(xùn)練數(shù)據(jù)的準(zhǔn)確預(yù)測(cè),但對(duì)新數(shù)據(jù)的預(yù)測(cè)偏差很大。一般的范圍在100-1000之間。
#2.early_stopping_rounds
這個(gè)參數(shù) early_stopping_rounds 提供了一種自動(dòng)查找理想值的方法,試驗(yàn)證分?jǐn)?shù)停止改進(jìn)時(shí)停止迭代。
我們可以為 n_estimators 設(shè)置一個(gè)較高值,然后使用 early_stopping_rounds來(lái)找到停止迭代的最佳時(shí)間。
my_model = XGBRegressor(n_estimators=1000) #評(píng)價(jià)模型在測(cè)試集上的表現(xiàn),也可以輸出每一步的分?jǐn)?shù) verbose=True my_model.fit(train_X, train_y, early_stopping_rounds=5, eval_set=[(test_X, test_y)], verbose=True) #[0] validation_0-rmse:181513 #Will train until validation_0-rmse hasn't improved in 5 rounds. #[1] validation_0-rmse:164369 #[2] validation_0-rmse:149195 #[3] validation_0-rmse:135397 #[4] validation_0-rmse:123108 #[5] validation_0-rmse:111850 #[6] validation_0-rmse:102150 #[7] validation_0-rmse:93362.6 #[8] validation_0-rmse:85537.3 #[9] validation_0-rmse:78620.8 #[10] validation_0-rmse:72306.5 #[11] validation_0-rmse:67021.3 #[12] validation_0-rmse:62228.3 # XGBRegressor(base_score=0.5, booster='gbtree', colsample_bylevel=1, # colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0, # max_depth=3, min_child_weight=1, missing=None, n_estimators=1000, # n_jobs=1, nthread=None, objective='reg:linear', random_state=0, # reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None, # silent=True, subsample=1)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
當(dāng)使用 early_stopping_rounds 參數(shù)時(shí),您需要留出一些數(shù)據(jù)來(lái)檢查要使用的輪數(shù),從以上實(shí)例代碼可以看出 n_estimators=1000 為停止迭代次數(shù)。
#3.learning_rate
以下是一個(gè)小技巧但很重要,可用于訓(xùn)練更好的xgboost模型:
一般來(lái)說(shuō),一個(gè)較小的 learning_rate(和較大的 n_estimators )將產(chǎn)生更精確的xgboost 模型,由于該模型在整個(gè)循環(huán)中進(jìn)行了更多的迭代,因此它也需要更長(zhǎng)的時(shí)間來(lái)訓(xùn)練。
我們用?GridSearchCV?來(lái)進(jìn)行調(diào)整 learning_rate 的值,以找到最合適的參數(shù):
from sklearn.model_selection import GridSearchCV from sklearn.model_selection import StratifiedKFold # 設(shè)定要調(diào)節(jié)的 learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3] my_model= XGBRegressor(n_estimators=1000) learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3] param_grid = dict(learning_rate=learning_rate) kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=7) grid_search = GridSearchCV(my_model, param_grid, n_jobs=-1, cv=kfold) grid_result = grid_search.fit(train_X, train_y) print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) #Best: 0.285843 using {'learning_rate': 0.01}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
#4.n_jobs
在運(yùn)行時(shí)的較大數(shù)據(jù)集上,可以使用并行性更快地構(gòu)建模型,通常將參數(shù)n_jobs設(shè)置為機(jī)器上的CPU的數(shù)量。對(duì)于較小的數(shù)據(jù)集,這個(gè)參數(shù)沒(méi)有任何作用。
可視化XGBoost樹(shù)
訓(xùn)練完模型后, 一般只是看看特征重要性(feature importance score),但是 XGBoost提供了一個(gè)方法plot_tree(),使得模型中每個(gè)決策樹(shù)是可以畫(huà)出來(lái)看看的。
import matplotlib.pyplot as plt from xgboost import plot_tree plot_tree(my_model,num_trees=0) #設(shè)置圖形的大小 plt.rcParams['figure.figsize'] = [50, 20] plt.show()- 1
- 2
- 3
- 4
- 5
- 6
- 7
可以得到以下這個(gè)的圖,plot_tree有些參數(shù)可以調(diào)整, 比如num_trees=0表示畫(huà)第一棵樹(shù),rankdir='LR’表示圖片是從左到右(Left to Right)。
上圖中f1,f2是feature ID,需要進(jìn)行轉(zhuǎn)換成特征屬性顯示:
#這個(gè)函數(shù)就是根據(jù)給定的特征名字(我直接使用了數(shù)據(jù)的列名稱(chēng)), 按照特定格式生成一個(gè)xgb.fmap文件 def ceate_feature_map(features): outfile = open('xgb.fmap', 'w') i = 0 for feat in features: outfile.write('{0}\t{1}\tq\n'.format(i, feat)) i = i + 1 outfile.close() ceate_feature_map(X.columns) #在調(diào)用plot_tree函數(shù)的時(shí)候, 直接指定fmap文件即可 plot_tree(my_model,num_trees=0,fmap='xgb.fmap') plt.rcParams['figure.figsize'] = [50, 20] plt.show()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
可視化XGBoost模型的另一種方法是顯示模型中原始數(shù)據(jù)集中每個(gè)要屬性的重要性,XGBoost有一個(gè)?plot_importance()?方法,可以展示特征的重要性。
from xgboost import plot_importance plot_importance(my_model) plt.rcParams['figure.figsize'] = [10, 10] plt.show()- 1
- 2
- 3
- 4
從圖中可以看出,特征屬性 f16 - GrLivArea得分最高,可以展示特征的重要性。因此,XGBoost還為我們提供了一種進(jìn)行特征選擇的方法!!
4.參考資料
1.xgboost作者講義PPT:https://homes.cs.washington.edu/~tqchen/pdf/BoostedTree.pdf
2.xgboost入門(mén)與實(shí)戰(zhàn)(原理篇):https://blog.csdn.net/sb19931201/article/details/52557382
3.史上最詳細(xì)的XGBoost實(shí)戰(zhàn):https://zhuanlan.zhihu.com/p/31182879
4.一文讀懂機(jī)器學(xué)習(xí)大殺器XGBOOST原理
5.A Gentle Introduction to XGBoost for Applied Machine Learning
轉(zhuǎn)載于:https://www.cnblogs.com/yumoye/p/10421153.html
總結(jié)
以上是生活随笔為你收集整理的XGBoost入门及实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 烟雨江湖熊掌怎么刷不出来?
- 下一篇: 王者荣耀战区怎么改?