機器學習實戰 | XGBoost建模應用詳解
作者:韓信子@ShowMeAI
教程地址:http://www.showmeai.tech/tutorials/41
本文地址:http://www.showmeai.tech/article-detail/204
宣告:版權所有,轉載請聯絡平臺與作者並註明出處
收藏ShowMeAI檢視更多精彩內容
引言
XGBoost是eXtreme Gradient Boosting的縮寫稱呼,它是一個非常強大的Boosting演算法工具包,優秀的效能(效果與速度)讓其在很長一段時間內霸屏資料科學比賽解決方案榜首,現在很多大廠的機器學習方案依舊會首選這個模型。XGBoost在平行計算效率、缺失值處理、控制過擬合、預測泛化能力上都變現非常優秀。
本篇內容ShowMeAI展開給大家講解XGBoost的工程應用方法,對於XGBoost原理知識感興趣的同學,歡迎參考ShowMeAI的另外一篇原理文章 圖解機器學習|XGBoost模型詳解。
1.XGBoost安裝
XGBoost作為常見的強大Python機器學習工具庫,安裝也比較簡單。
1.1 Python與IDE環境設定
python環境與IDE設定可以參考ShowMeAI文章 圖解python | 安裝與環境設定 進行設定。
1.2 工具庫安裝
(1) Linux/Mac等系統
這些系統下的XGBoost安裝,大家只要基於pip就可以輕鬆完成了,在命令列端輸入命令如下命令即可等待安裝完成。
pip install xgboost
大家也可以選擇國內的pip源,以獲得更好的安裝速度
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xgboost
(2) Windows系統
對於windows系統而言,比較高效便捷的安裝方式是:在網址http://www.lfd.uci.edu/~gohlke/pythonlibs/ 中去下載對應版本的的XGBoost安裝包,再通過如下命令安裝。
pip install xgboost‑1.5.1‑cp310‑cp310‑win32.whl
2.XGBoost資料讀取
應用XGBoost的第一步,需要載入所需的資料成為工具庫所能支援的格式形態。XGBoost可以載入多種資料格式的資料用於訓練建模:
- libsvm格式的文字資料。
- Numpy的二維陣列。
- XGBoost的二進位制的快取檔案。載入的資料儲存在物件DMatrix中。
XGBoost的SKLearn介面也支援對於Dataframe格式的資料(參考ShowMeAI的文章 Python資料分析|Pandas核心操作函式大全 進行更多瞭解)進行處理。
下面是不同格式的資料,XGBoost的載入方式。
- 載入libsvm格式的資料
dtrain1 = xgb.DMatrix('train.svm.txt')
- 載入二進位制的快取檔案
dtrain2 = xgb.DMatrix('train.svm.buffer')
- 載入numpy的陣列
data = np.random.rand(5,10) # 5 entities, each contains 10 features
label = np.random.randint(2, size=5) # binary target
dtrain = xgb.DMatrix( data, label=label)
- 將scipy.sparse格式的資料轉化為 DMatrix 格式
csr = scipy.sparse.csr_matrix( (dat, (row,col)) )
dtrain = xgb.DMatrix( csr )
- 將DMatrix格式的資料儲存成XGBoost的二進位制格式,在下次載入時可以提高載入速度,使用方式如下
dtrain = xgb.DMatrix('train.svm.txt')
dtrain.save_binary("train.buffer")
- 可以用如下方式處理DMatrix中的缺失值
dtrain = xgb.DMatrix( data, label=label, missing = -999.0)
- 當需要給樣本設定權重時,可以用如下方式
w = np.random.rand(5,1)
dtrain = xgb.DMatrix( data, label=label, missing = -999.0, weight=w)
3.XGBoost不同建模方式
3.1 內建建模方式:libsvm格式資料來源
XGBoost內建了建模方式,有如下的資料格式與核心訓練方法:
- 基於
DMatrix
格式的資料。 - 基於
xgb.train
介面訓練。
下面是官方的一個簡單示例,演示了讀取libsvm格式資料(成DMatrix
格式)並指定引數建模的過程。
# 匯入工具庫
import numpy as np
import scipy.sparse
import pickle
import xgboost as xgb
# 從libsvm檔案中讀取資料,做二分類
# 資料是libsvm的格式,如下樣本格式
#1 3:1 10:1 11:1 21:1 30:1 34:1 36:1 40:1 41:1 53:1 58:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 105:1 117:1 124:1
#0 3:1 10:1 20:1 21:1 23:1 34:1 36:1 39:1 41:1 53:1 56:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 106:1 116:1 120:1
#0 1:1 10:1 19:1 21:1 24:1 34:1 36:1 39:1 42:1 53:1 56:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 106:1 116:1 122:1
dtrain = xgb.DMatrix('./data/agaricus.txt.train')
dtest = xgb.DMatrix('./data/agaricus.txt.test')
# 超引數設定
# 主要是樹深、學習率、目標函式
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic' }
# 設定watchlist用於建模過程中觀測模型狀態
watchlist = [(dtest,'eval'), (dtrain,'train')]
num_round = 2
bst = xgb.train(param, dtrain, num_round, watchlist)
# 使用模型預測
preds = bst.predict(dtest)
# 判斷準確率
labels = dtest.get_label()
print('錯誤率為%f' % \
(sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) /float(len(preds))))
# 模型儲存
bst.save_model('./model/0001.model')
[0] eval-error:0.042831 train-error:0.046522
[1] eval-error:0.021726 train-error:0.022263
錯誤率為0.021726
3.2 內建建模方式:csv格式資料來源
下面的例子,輸入的資料來源是csv檔案,我們使用大家熟悉的pandas工具庫(參考ShowMeAI教程 資料分析系列教程 與 資料科學工具速查 | Pandas使用指南)把資料讀取為Dataframe格式,再構建Dmatrix格式輸入,後續使用內建建模方式進行訓練。
# 皮馬印第安人糖尿病資料集 包含很多欄位:懷孕次數 口服葡萄糖耐量試驗中血漿葡萄糖濃度 舒張壓(mm Hg) 三頭肌組織褶厚度(mm)
# 2小時血清胰島素(μU/ ml) 體重指數(kg/(身高(m)^2) 糖尿病系統功能 年齡(歲)
import pandas as pd
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
data.head()
# 匯入工具庫
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
# 用pandas讀入資料
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
# 做資料切分
train, test = train_test_split(data)
# 轉換成Dmatrix格式
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'
# 取出Dataframe的numpy陣列值去初始化DMatrix物件
xgtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)
xgtest = xgb.DMatrix(test[feature_columns].values, test[target_column].values)
#引數設定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }
# 設定watchlist用於檢視模型狀態
watchlist = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)
# 使用模型預測
preds = bst.predict(xgtest)
# 判斷準確率
labels = xgtest.get_label()
print('錯誤類為%f' % \
(sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) /float(len(preds))))
# 模型儲存
bst.save_model('./model/0002.model')
[0] eval-error:0.354167 train-error:0.194444
[1] eval-error:0.34375 train-error:0.170139
[2] eval-error:0.322917 train-error:0.170139
[3] eval-error:0.28125 train-error:0.161458
[4] eval-error:0.302083 train-error:0.147569
[5] eval-error:0.286458 train-error:0.138889
[6] eval-error:0.296875 train-error:0.142361
[7] eval-error:0.291667 train-error:0.144097
[8] eval-error:0.302083 train-error:0.130208
[9] eval-error:0.291667 train-error:0.130208
錯誤類為0.291667
3.3 預估器建模方式:SKLearn介面+Dataframe
XGBoost也支援用SKLearn中統一的預估器形態介面進行建模,如下為典型的參考案例,對於讀取為Dataframe格式的訓練集和測試集,可以直接使用XGBoost初始化XGBClassifier進行fit擬合訓練。使用方法與介面,和SKLearn中其他預估器一致。
# 匯入工具庫
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
# 用pandas讀入資料
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
# 做資料切分
train, test = train_test_split(data)
# 特徵列
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
# 標籤列
target_column = 'Outcome'
# 初始化模型
xgb_classifier = xgb.XGBClassifier(n_estimators=20,\
max_depth=4, \
learning_rate=0.1, \
subsample=0.7, \
colsample_bytree=0.7, \
eval_metric='error')
# Dataframe格式資料擬合模型
xgb_classifier.fit(train[feature_columns], train[target_column])
# 使用模型預測
preds = xgb_classifier.predict(test[feature_columns])
# 判斷準確率
print('錯誤類為%f' %((preds!=test[target_column]).sum()/float(test_y.shape[0])))
# 模型儲存
joblib.dump(xgb_classifier, './model/0003.model')
錯誤類為0.265625
['./model/0003.model']
4.模型調參與高階功能
4.1 XGBoost引數詳解
在執行XGBoost之前,必須設定三種類型成熟:general parameters,booster parameters和task parameters:
-
通用引數:General parameters
- 該引數控制在提升(boosting)過程中使用哪種booster,常用的booster有樹模型(tree)和線性模型(linear model)。
-
提升器引數:Booster parameters
- 這取決於使用哪種booster,包含樹模型booster和線性booster引數。
-
任務引數:Task parameters
- 控制學習的場景,例如在迴歸問題中會使用不同的引數控制排序。
(1) 通用引數
- booster [default=gbtree]
有兩種模型可以選擇gbtree和gblinear。gbtree使用基於樹的模型進行提升計算,gblinear使用線性模型進行提升計算。預設值為gbtree
- silent [default=0]
取0時表示打印出執行時資訊,取1時表示以緘默方式執行,不列印執行時資訊。預設值為0
- nthread
XGBoost執行時的執行緒數。預設值是當前系統可以獲得的最大執行緒數
- num_pbuffer
預測緩衝區大小,通常設定為訓練例項的數目。緩衝用於儲存最後一步提升的預測結果,無需人為設定。
- num_feature
Boosting過程中用到的特徵維數,設定為特徵個數。XGBoost會自動設定,無需人為設定。
(2) 樹模型booster引數
- eta [default=0.3]
為了防止過擬合,更新過程中用到的收縮步長。在每次提升計算之後,演算法會直接獲得新特徵的權重。 eta通過縮減特徵的權重使提升計算過程更加保守。預設值為0.3 取值範圍為:[0,1]
- gamma [default=0]
樹要進一步分裂生長所需的最小loss減小值. the larger, the more conservative the algorithm will be. 取值範圍為:[0,∞]
- max_depth [default=6]
數的最大深度。預設值為6 取值範圍為:[1,∞]
- min_child_weight [default=1]
孩子節點中最小的樣本權重和。如果一個葉子節點的樣本權重和小於min_child_weight則拆分過程結束。在現行迴歸模型中,這個引數是指建立每個模型所需要的最小樣本數。該成熟越大演算法越conservative 取值範圍為:[0,∞]
- max_delta_step [default=0]
我們允許每個樹的權重被估計的值。如果它的值被設定為0,意味著沒有約束;如果它被設定為一個正值,它能夠使得更新的步驟更加保守。通常這個引數是沒有必要的,但是如果在邏輯迴歸中類極其不平衡這時候他有可能會起到幫助作用。把它範圍設定為1-10之間也許能控制更新。 取值範圍為:[0,∞]
- subsample [default=1]
用於訓練模型的子樣本佔整個樣本集合的比例。如果設定為0.5則意味著XGBoost將隨機的從整個樣本集合中隨機的抽取出50%的子樣本建立樹模型,這能夠防止過擬合。 取值範圍為:(0,1]
- colsample_bytree [default=1]
在建立樹時對特徵取樣的比例。預設值為1 取值範圍為:(0,1]
(3) 線性Booster引數
- lambda [default=0]
L2正則的懲罰係數
- alpha [default=0]
L1正則的懲罰係數
- lambda_bias
在偏置上的L2正則。預設值為0(在L1上沒有偏置項的正則,因為L1時偏置不重要)
(4) 任務引數
-
objective [ default=reg:linear ]
- 定義學習任務及相應的學習目標
- 可選的目標函式如下:
-
reg:linear
: 線性迴歸。 -
reg:logistic
: 邏輯迴歸。 -
binary:logistic
: 二分類的邏輯迴歸問題,輸出為概率。 -
binary:logitraw
: 二分類的邏輯迴歸問題,輸出的結果為wTx。 -
count:poisson
: 計數問題的poisson迴歸,輸出結果為poisson分佈。在poisson迴歸中,max_delta_step的預設值為0.7。(used to safeguard optimization)。 -
multi:softmax
:讓XGBoost採用softmax目標函式處理多分類問題,同時需要設定引數num_class(類別個數)。 -
multi:softprob
:和softmax一樣,但是輸出的是ndata * nclass的向量,可以將該向量reshape成ndata行nclass列的矩陣。沒行資料表示樣本所屬於每個類別的概率。 -
rank:pairwise
:set XGBoost to do ranking task by minimizing the pairwise loss。
-
-
base_score [ default=0.5 ]
- 所有例項的初始化預測分數,全域性偏置;
- 為了足夠的迭代次數,改變這個值將不會有太大的影響。
-
eval_metric [ default according to objective ]
- 校驗資料所需要的評價指標,不同的目標函式將會有預設的評價指標(rmse for regression, and error for classification, mean average precision for ranking)
- 使用者可以新增多種評價指標,對於Python使用者要以list傳遞引數對給程式,而不是map引數list引數不會覆蓋`eval_metric’
- 可供的選擇如下:
-
rmse
:root mean square error -
logloss
:negative log-likelihood -
error
:Binary classification error rate. It is calculated as #(wrong cases)/#(all cases). For the predictions, the evaluation will regard the instances with prediction value larger than 0.5 as positive instances, and the others as negative instances. -
merror
:Multiclass classification error rate. It is calculated as #(wrongcases)#(allcases). -
mlogloss
:Multiclass logloss -
auc
:Area under the curve for ranking evaluation. -
ndcg
:Normalized Discounted Cumulative Gain -
map
:Mean average precision -
ndcg@n
,map@n
:n can be assigned as an integer to cut off the top positions in the lists for evaluation. -
ndcg-
,map-
,ndcg@n-
,map@n-
:In XGBoost, NDCG and MAP will evaluate the score of a list without any positive samples as 1. By adding-
in the evaluation metric XGBoost will evaluate these score as 0 to be consistent under some conditions. training repeatively
-
-
seed [ default=0 ]
- 隨機數的種子。預設值為0
4.2 內建調參優化
(1) 交叉驗證
XGBoost自帶實驗與調參的一些方法,如下為交叉驗證方法xgb.cv
。
xgb.cv(param, dtrain, num_round, nfold=5,metrics={'error'}, seed = 0)
(2) 新增預處理
我們可以把資料建模過程中的一些設定加到交叉驗證環節裡,比如對於不同類別的樣本加權,可以參考下列程式碼示例
# 計算正負樣本比,調整樣本權重
def fpreproc(dtrain, dtest, param):
label = dtrain.get_label()
ratio = float(np.sum(label == 0)) / np.sum(label==1)
param['scale_pos_weight'] = ratio
return (dtrain, dtest, param)
# 先做預處理,計算樣本權重,再做交叉驗證
xgb.cv(param, dtrain, num_round, nfold=5,
metrics={'auc'}, seed = 0, fpreproc = fpreproc)
(3) 自定義損失函式與評估準則
XGBoost支援在訓練過程中,自定義損失函式和評估準則,其中損失函式的定義需要返回損失函式一階和二階導數的計算方法,評估準則部分需要對資料的label和預估值進行計算。其中損失函式用於訓練過程中的樹結構學習,而評估準則很多時候是用在驗證集上進行效果評估。
print('使用自定義損失函式進行交叉驗證')
# 自定義損失函式,需要提供損失函式的一階導和二階導
def logregobj(preds, dtrain):
labels = dtrain.get_label()
preds = 1.0 / (1.0 + np.exp(-preds))
grad = preds - labels
hess = preds * (1.0-preds)
return grad, hess
# 自定義評估準則,評估預估值和標準答案之間的差距
def evalerror(preds, dtrain):
labels = dtrain.get_label()
return 'error', float(sum(labels != (preds > 0.0))) / len(labels)
watchlist = [(dtest,'eval'), (dtrain,'train')]
param = {'max_depth':3, 'eta':0.1, 'silent':1}
num_round = 5
# 自定義損失函式訓練
bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
# 交叉驗證
xgb.cv(param, dtrain, num_round, nfold = 5, seed = 0, obj = logregobj, feval=evalerror)
使用自定義損失函式進行交叉驗證
[0] eval-rmse:0.306901 train-rmse:0.306164 eval-error:0.518312 train-error:0.517887
[1] eval-rmse:0.179189 train-rmse:0.177278 eval-error:0.518312 train-error:0.517887
[2] eval-rmse:0.172565 train-rmse:0.171728 eval-error:0.016139 train-error:0.014433
[3] eval-rmse:0.269612 train-rmse:0.27111 eval-error:0.016139 train-error:0.014433
[4] eval-rmse:0.396903 train-rmse:0.398256 eval-error:0.016139 train-error:0.014433
(4) 只用前n顆樹預測
對於boosting模型來說,最後會訓練得到很多基學習器(在XGBoost中很多時候是很多棵樹),我們可以一次完整訓練,只用前n棵樹的整合來完成預測。
#!/usr/bin/python
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
# 基本例子,從csv檔案中讀取資料,做二分類
# 用pandas讀入資料
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
# 做資料切分
train, test = train_test_split(data)
# 轉換成Dmatrix格式
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'
xgtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)
xgtest = xgb.DMatrix(test[feature_columns].values, test[target_column].values)
#引數設定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }
# 設定watchlist用於檢視模型狀態
watchlist = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)
# 只用第1顆樹預測
ypred1 = bst.predict(xgtest, ntree_limit=1)
# 用前9顆樹預測
ypred2 = bst.predict(xgtest, ntree_limit=9)
label = xgtest.get_label()
print('用前1顆樹預測的錯誤率為 %f' % (np.sum((ypred1>0.5)!=label) /float(len(label))))
print('用前9顆樹預測的錯誤率為 %f' % (np.sum((ypred2>0.5)!=label) /float(len(label))))
[0] eval-error:0.255208 train-error:0.196181
[1] eval-error:0.234375 train-error:0.175347
[2] eval-error:0.25 train-error:0.163194
[3] eval-error:0.229167 train-error:0.149306
[4] eval-error:0.213542 train-error:0.154514
[5] eval-error:0.21875 train-error:0.152778
[6] eval-error:0.21875 train-error:0.154514
[7] eval-error:0.213542 train-error:0.138889
[8] eval-error:0.1875 train-error:0.147569
[9] eval-error:0.1875 train-error:0.144097
用前1顆樹預測的錯誤率為 0.255208
用前9顆樹預測的錯誤率為 0.187500
4.3 預估器調參優化
(1) SKLearn形態介面實驗評估
XGBoost有SKLearn預估器形態的介面,整體使用方法和SKLearn中其他預估器一致,如下是手動對資料做交叉驗證,注意到這裡直接使用XGBClassifier
對Dataframe資料進行fit擬合和評估。
import pickle
import xgboost as xgb
import numpy as np
from sklearn.model_selection import KFold, train_test_split, GridSearchCV
from sklearn.metrics import confusion_matrix, mean_squared_error
from sklearn.datasets import load_iris, load_digits, load_boston
rng = np.random.RandomState(31337)
# 二分類:混淆矩陣
print("數字0和1的二分類問題")
digits = load_digits(2)
y = digits['target']
X = digits['data']
# 資料切分物件
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折資料上的交叉驗證")
# 2折交叉驗證
for train_index, test_index in kf.split(X):
xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
predictions = xgb_model.predict(X[test_index])
actuals = y[test_index]
print("混淆矩陣:")
print(confusion_matrix(actuals, predictions))
#多分類:混淆矩陣
print("\nIris: 多分類")
iris = load_iris()
y = iris['target']
X = iris['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折資料上的交叉驗證")
for train_index, test_index in kf.split(X):
xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
predictions = xgb_model.predict(X[test_index])
actuals = y[test_index]
print("混淆矩陣:")
print(confusion_matrix(actuals, predictions))
#迴歸問題:MSE
print("\n波士頓房價迴歸預測問題")
boston = load_boston()
y = boston['target']
X = boston['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折資料上的交叉驗證")
for train_index, test_index in kf.split(X):
xgb_model = xgb.XGBRegressor().fit(X[train_index],y[train_index])
predictions = xgb_model.predict(X[test_index])
actuals = y[test_index]
print("MSE:",mean_squared_error(actuals, predictions))
數字0和1的二分類問題
在2折資料上的交叉驗證
混淆矩陣:
[[87 0]
[ 1 92]]
混淆矩陣:
[[91 0]
[ 3 86]]
Iris: 多分類
在2折資料上的交叉驗證
混淆矩陣:
[[19 0 0]
[ 0 31 3]
[ 0 1 21]]
混淆矩陣:
[[31 0 0]
[ 0 16 0]
[ 0 3 25]]
波士頓房價迴歸預測問題
在2折資料上的交叉驗證
MSE: 9.860776812557337
MSE: 15.942418468446029
(2) 網格搜尋調參
上面提到XGBoost的預估器介面,整體使用方法和SKLearn中其他預估器一致,所以我們也可以使用SKLearn中的超引數調優方法來進行模型調優。
如下是一個典型的網格搜尋交法調優超引數的程式碼示例,我們會給出候選引數列表字典,通過GridSearchCV
進行交叉驗證實驗評估,選出XGBoost在候選引數中最優的超引數。
print("引數最優化:")
y = boston['target']
X = boston['data']
xgb_model = xgb.XGBRegressor()
clf = GridSearchCV(xgb_model,
{'max_depth': [2,4,6],
'n_estimators': [50,100,200]}, verbose=1)
clf.fit(X,y)
print(clf.best_score_)
print(clf.best_params_)
引數最優化:
Fitting 3 folds for each of 9 candidates, totalling 27 fits
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
0.6001029721598573
{'max_depth': 4, 'n_estimators': 100}
[Parallel(n_jobs=1)]: Done 27 out of 27 | elapsed: 1.3s finished
(3) early-stopping早停
XGBoost模型有時候會因為不停疊加新的樹(修正訓練集上擬合尚不正確的一些樣本),可能會因為對於訓練集過度學習而導致模型過擬合。early stopping早停止是一個有效的策略,具體的做法是,在訓練集不斷追加樹學習的過程中,對驗證集上的表現進行監控,如果出現一定輪次評估準則都沒有優化提升的情況,則回溯到歷史上驗證集最好的點,儲存為最佳模型。
下面是對應的程式碼示例,其中引數early_stopping_rounds
設定了驗證集上能接受的效果不提升的最多輪次數,eval_set
指定了驗證資料集。
# 在訓練集上學習模型,一顆一顆樹新增,在驗證集上看效果,當驗證集效果不再提升,停止樹的新增與生長
X = digits['data']
y = digits['target']
X_train, X_val, y_train, y_val = train_test_split(X, y, random_state=0)
clf = xgb.XGBClassifier()
clf.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="auc",
eval_set=[(X_val, y_val)])
[0] validation_0-auc:0.999497
Will train until validation_0-auc hasn't improved in 10 rounds.
[1] validation_0-auc:0.999497
[2] validation_0-auc:0.999497
[3] validation_0-auc:0.999749
[4] validation_0-auc:0.999749
[5] validation_0-auc:0.999749
[6] validation_0-auc:0.999749
[7] validation_0-auc:0.999749
[8] validation_0-auc:0.999749
[9] validation_0-auc:0.999749
[10] validation_0-auc:1
[11] validation_0-auc:1
[12] validation_0-auc:1
[13] validation_0-auc:1
[14] validation_0-auc:1
[15] validation_0-auc:1
[16] validation_0-auc:1
[17] validation_0-auc:1
[18] validation_0-auc:1
[19] validation_0-auc:1
[20] validation_0-auc:1
Stopping. Best iteration:
[10] validation_0-auc:1
XGBClassifier(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=100,
n_jobs=1, nthread=None, objective='binary:logistic', random_state=0,
reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
silent=True, subsample=1)
(4) 特徵重要度
XGBoost建模過程中,還可以學習到對應的特徵重要度資訊,並儲存在模型的feature_importances_
屬性中。如下為繪製特徵重要度的視覺化程式碼:
iris = load_iris()
y = iris['target']
X = iris['data']
xgb_model = xgb.XGBClassifier().fit(X,y)
print('特徵排序:')
feature_names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
feature_importances = xgb_model.feature_importances_
indices = np.argsort(feature_importances)[::-1]
for index in indices:
print("特徵 %s 重要度為 %f" %(feature_names[index], feature_importances[index]))
%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(16,8))
plt.title("feature importances")
plt.bar(range(len(feature_importances)), feature_importances[indices], color='b')
plt.xticks(range(len(feature_importances)), np.array(feature_names)[indices], color='b')
特徵排序:
特徵 petal_length 重要度為 0.415567
特徵 petal_width 重要度為 0.291557
特徵 sepal_length 重要度為 0.179420
特徵 sepal_width 重要度為 0.113456
(5) 並行訓練加速
在多資源的情況下,XGBoost可以實現並行訓練加速,示例程式碼如下:
import os
if __name__ == "__main__":
try:
from multiprocessing import set_start_method
except ImportError:
raise ImportError("Unable to import multiprocessing.set_start_method."
" This example only runs on Python 3.4")
#set_start_method("forkserver")
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_boston
import xgboost as xgb
rng = np.random.RandomState(31337)
print("Parallel Parameter optimization")
boston = load_boston()
os.environ["OMP_NUM_THREADS"] = "2" # or to whatever you want
y = boston['target']
X = boston['data']
xgb_model = xgb.XGBRegressor()
clf = GridSearchCV(xgb_model, {'max_depth': [2, 4, 6],
'n_estimators': [50, 100, 200]}, verbose=1,
n_jobs=2)
clf.fit(X, y)
print(clf.best_score_)
print(clf.best_params_)
Parallel Parameter optimization
Fitting 3 folds for each of 9 candidates, totalling 27 fits
[Parallel(n_jobs=2)]: Using backend LokyBackend with 2 concurrent workers.
[Parallel(n_jobs=2)]: Done 24 out of 27 | elapsed: 2.2s remaining: 0.3s
0.6001029721598573
{'max_depth': 4, 'n_estimators': 100}
[Parallel(n_jobs=2)]: Done 27 out of 27 | elapsed: 2.4s finished
參考資料
ShowMeAI系列教程推薦
- 圖解Python程式設計:從入門到精通系列教程
- 圖解資料分析:從入門到精通系列教程
- 圖解AI數學基礎:從入門到精通系列教程
- 圖解大資料技術:從入門到精通系列教程
- 圖解機器學習演算法:從入門到精通系列教程
- 機器學習實戰:手把手教你玩轉機器學習系列