在XGBoost算法原理小結中,咱們討論了XGBoost的算法原理,這一片咱們討論如何使用XGBoost的Python類庫,以及一些重要參數的意義和調參思路。html
本文主要參考了XGBoost的Python文檔 和 XGBoost的參數文檔。node
XGBoost除了支持Python外,也支持R,Java等語言。本文關注於Python的XGBoost類庫,安裝使用"pip install xgboost"便可,目前使用的是XGBoost的0.90版本。XGBoost類庫除了支持決策樹做爲弱學習器外,還支持線性分類器,以及帶DropOut的決策樹DART,不過一般狀況下,咱們使用默認的決策樹弱學習器便可,本文也只會討論使用默認決策樹弱學習器的XGBoost。python
XGBoost有2種Python接口風格。一種是XGBoost自帶的原生Python API接口,另外一種是sklearn風格的API接口,二者的實現是基本同樣的,僅僅有細微的API使用的不一樣,主要體如今參數命名上,以及數據集的初始化上面。git
完整示例參見個人Github代碼。github
XGBoost的類庫的2種接口風格,咱們先來看看原生Python API接口如何使用。算法
原生XGBoost須要先把數據集按輸入特徵部分,輸出部分分開,而後放到一個DMatrix數據結構裏面,這個DMatrix咱們不須要關內心面的細節,使用咱們的訓練集X和y初始化便可。api
import pandas as pd import numpy as np import xgboost as xgb import matplotlib.pylab as plt %matplotlib inline from sklearn.model_selection import GridSearchCV from sklearn.model_selection import train_test_split
from sklearn.datasets.samples_generator import make_classification # X爲樣本特徵,y爲樣本類別輸出, 共10000個樣本,每一個樣本20個特徵,輸出有2個類別,沒有冗餘特徵,每一個類別一個簇 X, y = make_classification(n_samples=10000, n_features=20, n_redundant=0, n_clusters_per_class=1, n_classes=2, flip_y=0.1)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
dtrain = xgb.DMatrix(X_train,y_train) dtest = xgb.DMatrix(X_test,y_test)
上面的代碼中,咱們隨機初始化了一個二分類的數據集,而後分紅了訓練集和驗證集。使用訓練集和驗證集分別初始化了一個DMatrix,有了DMatrix,就能夠作訓練和預測了。簡單的示例代碼以下:微信
param = {'max_depth':5, 'eta':0.5, 'verbosity':1, 'objective':'binary:logistic'} raw_model = xgb.train(param, dtrain, num_boost_round=20)
from sklearn.metrics import accuracy_score pred_train_raw = raw_model.predict(dtrain) for i in range(len(pred_train_raw)): if pred_train_raw[i] >; 0.5: pred_train_raw[i]=1 else: pred_train_raw[i]=0 print (accuracy_score(dtrain.get_label(), pred_train_raw))
訓練集的準確率我這裏輸出是0.9664。再看看驗證集的表現:數據結構
pred_test_raw = raw_model.predict(dtest) for i in range(len(pred_test_raw)): if pred_test_raw[i] >; 0.5: pred_test_raw[i]=1 else: pred_test_raw[i]=0 print (accuracy_score(dtest.get_label(), pred_test_raw))
驗證集的準確率我這裏的輸出是0.9408,已經很高了。併發
不過對於我這樣用慣sklearn風格API的,仍是不太喜歡原生Python API接口,既然有sklearn的wrapper,那麼就儘可能使用sklearn風格的接口吧。
對於sklearn風格的接口,主要有2個類可使用,一個是分類用的XGBClassifier,另外一個是迴歸用的XGBRegressor。在使用這2個類的使用,對於算法的參數輸入也有2種方式,第一種就是仍然使用和原始API同樣的參數命名集合,另外一種是使用sklearn風格的參數命名。咱們這裏先看看如何使用和原始API同樣的參數命名集合。
其實就是使用XGBClassifier/XGBRegressor的**kwargs參數,把上面原生參數的params集合放進去,代碼以下:
sklearn_model_raw = xgb.XGBClassifier(**param) sklearn_model_raw.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="error", eval_set=[(X_test, y_test)])
裏面的param其實就是2.1節裏面定義的:
param = {'max_depth':5, 'eta':0.5, 'verbosity':1, 'objective':'binary:logistic'}
使用sklearn風格的接口,卻使用原始的參數名定義,感受仍是有點怪,因此我通常仍是習慣使用另外一種風格接口,sklearn風格的參數命名。
使用sklearn風格的接口,並使用sklearn風格的參數,是我推薦的方式,主要是這樣作和GBDT之類的sklearn庫使用起來沒有什麼兩樣了,也可使用sklearn的網格搜索。
不過這樣作的話,參數定義命名和2.1與2.2節就有些不一樣了。具體的參數意義咱們後面講,咱們看看分類的算法初始化,訓練與調用的簡單過程:
sklearn_model_new = xgb.XGBClassifier(max_depth=5,learning_rate= 0.5, verbosity=1, objective='binary:logistic',random_state=1)
能夠看到,參數定義直接放在了XGBClassifier的類參數裏,和sklearn相似。你們能夠看到以前兩節咱們定義的步長eta,這裏變成了另外一個名字learning_rate。
在初始化後,訓練和預測的方法就和2.2節沒有區別了。
sklearn_model_new.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="error", eval_set=[(X_test, y_test)])
在第二節咱們已經嘗試使用XGBoost類庫了,可是對於XGBoost的類庫參數並無過多討論。這裏咱們就詳細討論下,主要以2.3節的sklearn風格參數爲主來進行討論。這些參數我會和以前講的scikit-learn 梯度提高樹(GBDT)調參小結中的參數定義對應,這樣若是你們對GBDT的調參很熟悉了,那麼XGBoost的調參也就掌握90%了。
XGBoost的類庫參數主要包括boosting框架參數,弱學習器參數以及其餘參數。
對於XGBoost的框架參數,最重要的是3個參數: booster,n_estimators和objectve。
1) booster決定了XGBoost使用的弱學習器類型,能夠是默認的gbtree, 也就是CART決策樹,還能夠是線性弱學習器gblinear以及DART。通常來講,咱們使用gbtree就能夠了,不須要調參。
2) n_estimators則是很是重要的要調的參數,它關係到咱們XGBoost模型的複雜度,由於它表明了咱們決策樹弱學習器的個數。這個參數對應sklearn GBDT的n_estimators。n_estimators過小,容易欠擬合,n_estimators太大,模型會過於複雜,通常須要調參選擇一個適中的數值。
3) objective表明了咱們要解決的問題是分類仍是迴歸,或其餘問題,以及對應的損失函數。具體能夠取的值不少,通常咱們只關心在分類和迴歸的時候使用的參數。
在迴歸問題objective通常使用reg:squarederror ,即MSE均方偏差。二分類問題通常使用binary:logistic, 多分類問題通常使用multi:softmax。
這裏咱們只討論使用gbtree默認弱學習器的參數。 要調參的參數主要是決策樹的相關參數以下:
1) max_depth: 控制樹結構的深度,數據少或者特徵少的時候能夠無論這個值。若是模型樣本量多,特徵也多的狀況下,須要限制這個最大深度,具體的取值通常要網格搜索調參。這個參數對應sklearn GBDT的max_depth。
2) min_child_weight: 最小的子節點權重閾值,若是某個樹節點的權重小於這個閾值,則不會再分裂子樹,即這個樹節點就是葉子節點。這裏樹節點的權重使用的是該節點全部樣本的二階導數的和,即XGBoost原理篇裏面的\(H_{tj}\):
\[ H_{tj} = \sum\limits_{x_i \in R_{tj}}h_{ti} \]
這個值須要網格搜索尋找最優值,在sklearn GBDT裏面,沒有徹底對應的參數,不過min_samples_split從另外一個角度起到了閾值限制。
3) gamma: XGBoost的決策樹分裂所帶來的損失減少閾值。也就是咱們在嘗試樹結構分裂時,會嘗試最大數下式:
\[ \max \frac{1}{2}\frac{G_L^2}{H_L + \lambda} + \frac{1}{2}\frac{G_R^2}{H_R+\lambda} - \frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+ \lambda} - \gamma \]
這個最大化後的值須要大於咱們的gamma,才能繼續分裂子樹。這個值也須要網格搜索尋找最優值。
4) subsample: 子採樣參數,這個也是不放回抽樣,和sklearn GBDT的subsample做用同樣。選擇小於1的比例能夠減小方差,即防止過擬合,可是會增長樣本擬合的誤差,所以取值不能過低。初期能夠取值1,若是發現過擬合後能夠網格搜索調參找一個相對小一些的值。
5) colsample_bytree/colsample_bylevel/colsample_bynode: 這三個參數都是用於特徵採樣的,默認都是不作採樣,即便用全部的特徵創建決策樹。colsample_bytree控制整棵樹的特徵採樣比例,colsample_bylevel控制某一層的特徵採樣比例,而colsample_bynode控制某一個樹節點的特徵採樣比例。好比咱們一共64個特徵,則假設colsample_bytree,colsample_bylevel和colsample_bynode都是0.5,則某一個樹節點分裂時會隨機採樣8個特徵來嘗試分裂子樹。
6) reg_alpha/reg_lambda: 這2個是XGBoost的正則化參數。reg_alpha是L1正則化係數,reg_lambda是L1正則化係數,在原理篇裏咱們討論了XGBoost的正則化損失項部分:
\[ \Omega(h_t) = \gamma J + \frac{\lambda}{2}\sum\limits_{j=1}^Jw_{tj}^2 \]
上面這些參數都是須要調參的,不過通常先調max_depth,min_child_weight和gamma。若是發現有過擬合的狀況下,再嘗試調後面幾個參數。
XGBoost還有一些其餘的參數須要注意,主要是learning_rate。
learning_rate控制每一個弱學習器的權重縮減係數,和sklearn GBDT的learning_rate相似,較小的learning_rate意味着咱們須要更多的弱學習器的迭代次數。一般咱們用步長和迭代最大次數一塊兒來決定算法的擬合效果。因此這兩個參數n_estimators和learning_rate要一塊兒調參纔有效果。固然也能夠先固定一個learning_rate ,而後調完n_estimators,再調完其餘全部參數後,最後再來調learning_rate和n_estimators。
此外,n_jobs控制算法的併發線程數, scale_pos_weight用於類別不平衡的時候,負例和正例的比例。相似於sklearn中的class_weight。importance_type則能夠查詢各個特徵的重要性程度。能夠選擇「gain」, 「weight」, 「cover」, 「total_gain」 或者 「total_cover」。最後能夠經過調用booster的get_score方法獲取對應的特徵權重。「weight」經過特徵被選中做爲分裂特徵的計數來計算重要性,「gain」和「total_gain」則經過分別計算特徵被選中作分裂特徵時帶來的平均增益和總增益來計算重要性。「cover」和 「total_cover」經過計算特徵被選中作分裂時的平均樣本覆蓋度和整體樣本覆蓋度來來計算重要性。
XGBoost能夠和sklearn的網格搜索類GridSeachCV結合使用來調參,使用時和普通sklearn分類迴歸算法沒有區別。具體的流程的一個示例以下:
gsCv = GridSearchCV(sklearn_model_new, {'max_depth': [4,5,6], 'n_estimators': [5,10,20]}) gsCv.fit(X_train,y_train)
print(gsCv.best_score_) print(gsCv.best_params_)
我這裏的輸出是:
0.9533333333333334
{'max_depth': 4, 'n_estimators': 10}
接着嘗試在上面搜索的基礎上調learning_rate :
sklearn_model_new2 = xgb.XGBClassifier(max_depth=4,n_estimators=10,verbosity=1, objective='binary:logistic',random_state=1) gsCv2 = GridSearchCV(sklearn_model_new2, {'learning_rate ': [0.3,0.5,0.7]}) gsCv2.fit(X_train,y_train)
print(gsCv2.best_score_) print(gsCv2.best_params_)
我這裏的輸出是:
0.9516
{'learning_rate ': 0.3}
固然實際狀況這裏須要繼續調參,這裏假設咱們已經調參完畢,咱們嘗試用驗證集看看效果:
sklearn_model_new2 = xgb.XGBClassifier(max_depth=4,learning_rate= 0.3, verbosity=1, objective='binary:logistic',n_estimators=10) sklearn_model_new2.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="error", eval_set=[(X_test, y_test)])
最後的輸出是:
[9] validation_0-error:0.0588
也就是驗證集的準確率是94.12%。
咱們能夠經過驗證集的準確率來判斷咱們前面網格搜索調參是否起到了效果。實際處理的時候須要反覆搜索參數並驗證。
以上就是XGBoost的類庫使用總結了,但願能夠幫到要用XGBoost解決實際問題的朋友們。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: 微信:nickchen121)