機(jī)器學(xué)習(xí)實戰(zhàn) | XGBoost建模應(yīng)用詳解

引言

XGBoost是eXtreme Gradient Boosting的縮寫稱呼,它是一個非常強(qiáng)大的Boosting算法工具包,優(yōu)秀的性能(效果與速度)讓其在很長一段時間內(nèi)霸屏數(shù)據(jù)科學(xué)比賽解決方案榜首,現(xiàn)在很多大廠的機(jī)器學(xué)習(xí)方案依舊會首選這個模型功偿。XGBoost在并行計算效率店印、缺失值處理念搬、控制過擬合、預(yù)測泛化能力上都變現(xiàn)非常優(yōu)秀涌矢。

本篇內(nèi)容ShowMeAI展開給大家講解XGBoost的工程應(yīng)用方法掖举,對于XGBoost原理知識感興趣的同學(xué),歡迎參考ShowMeAI的另外一篇原理文章 圖解機(jī)器學(xué)習(xí)|XGBoost模型詳解娜庇。

1.XGBoost安裝

XGBoost作為常見的強(qiáng)大Python機(jī)器學(xué)習(xí)工具庫塔次,安裝也比較簡單方篮。

1.1 Python與IDE環(huán)境設(shè)置

python環(huán)境與IDE設(shè)置可以參考ShowMeAI文章 圖解python | 安裝與環(huán)境設(shè)置 進(jìn)行設(shè)置。

1.2 工具庫安裝

(1) Linux/Mac等系統(tǒng)

這些系統(tǒng)下的XGBoost安裝励负,大家只要基于pip就可以輕松完成了藕溅,在命令行端輸入命令如下命令即可等待安裝完成。

pip install xgboost

大家也可以選擇國內(nèi)的pip源继榆,以獲得更好的安裝速度

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xgboost

(2) Windows系統(tǒng)

對于windows系統(tǒng)而言巾表,比較高效便捷的安裝方式是:在網(wǎng)址http://www.lfd.uci.edu/~gohlke/pythonlibs/ 中去下載對應(yīng)版本的的XGBoost安裝包,再通過如下命令安裝略吨。

pip install xgboost?1.5.1?cp310?cp310?win32.whl

2.XGBoost數(shù)據(jù)讀取

應(yīng)用XGBoost的第一步集币,需要加載所需的數(shù)據(jù)成為工具庫所能支持的格式形態(tài)。XGBoost可以加載多種數(shù)據(jù)格式的數(shù)據(jù)用于訓(xùn)練建模:

  • libsvm格式的文本數(shù)據(jù)晋南。
  • Numpy的二維數(shù)組惠猿。
  • XGBoost的二進(jìn)制的緩存文件。加載的數(shù)據(jù)存儲在對象DMatrix中负间。

XGBoost的SKLearn接口也支持對于Dataframe格式的數(shù)據(jù)(參考ShowMeAI的文章 Python數(shù)據(jù)分析|Pandas核心操作函數(shù)大全 進(jìn)行更多了解)進(jìn)行處理偶妖。

下面是不同格式的數(shù)據(jù),XGBoost的加載方式政溃。

  • 加載libsvm格式的數(shù)據(jù)
dtrain1 = xgb.DMatrix('train.svm.txt')
  • 加載二進(jìn)制的緩存文件
dtrain2 = xgb.DMatrix('train.svm.buffer')
  • 加載numpy的數(shù)組
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格式的數(shù)據(jù)轉(zhuǎn)化為 DMatrix 格式
csr = scipy.sparse.csr_matrix( (dat, (row,col)) )
dtrain = xgb.DMatrix( csr ) 
  • 將DMatrix格式的數(shù)據(jù)保存成XGBoost的二進(jìn)制格式趾访,在下次加載時可以提高加載速度,使用方式如下
dtrain = xgb.DMatrix('train.svm.txt')
dtrain.save_binary("train.buffer")
  • 可以用如下方式處理DMatrix中的缺失值
dtrain = xgb.DMatrix( data, label=label, missing = -999.0)
  • 當(dāng)需要給樣本設(shè)置權(quán)重時董虱,可以用如下方式
w = np.random.rand(5,1)
dtrain = xgb.DMatrix( data, label=label, missing = -999.0, weight=w)

3.XGBoost不同建模方式

3.1 內(nèi)置建模方式:libsvm格式數(shù)據(jù)源

XGBoost內(nèi)置了建模方式扼鞋,有如下的數(shù)據(jù)格式與核心訓(xùn)練方法:

  • 基于DMatrix格式的數(shù)據(jù)。
  • 基于xgb.train接口訓(xùn)練愤诱。

下面是官方的一個簡單示例云头,演示了讀取libsvm格式數(shù)據(jù)(成DMatrix格式)并指定參數(shù)建模的過程。

# 導(dǎo)入工具庫
import numpy as np
import scipy.sparse
import pickle
import xgboost as xgb

# 從libsvm文件中讀取數(shù)據(jù)淫半,做二分類
# 數(shù)據(jù)是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')

# 超參數(shù)設(shè)定
# 主要是樹深、學(xué)習(xí)率科吭、目標(biāo)函數(shù)
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic' }

# 設(shè)定watchlist用于建模過程中觀測模型狀態(tài)
watchlist  = [(dtest,'eval'), (dtrain,'train')]
num_round = 2
bst = xgb.train(param, dtrain, num_round, watchlist)

# 使用模型預(yù)測
preds = bst.predict(dtest)

# 判斷準(zhǔn)確率
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 內(nèi)置建模方式:csv格式數(shù)據(jù)源

下面的例子昏滴,輸入的數(shù)據(jù)源是csv文件,我們使用大家熟悉的pandas工具庫(參考ShowMeAI教程 數(shù)據(jù)分析系列教程數(shù)據(jù)科學(xué)工具速查 | Pandas使用指南)把數(shù)據(jù)讀取為Dataframe格式对人,再構(gòu)建Dmatrix格式輸入谣殊,后續(xù)使用內(nèi)置建模方式進(jìn)行訓(xùn)練。

# 皮馬印第安人糖尿病數(shù)據(jù)集 包含很多字段:懷孕次數(shù) 口服葡萄糖耐量試驗中血漿葡萄糖濃度 舒張壓(mm Hg) 三頭肌組織褶厚度(mm) 
# 2小時血清胰島素(μU/ ml) 體重指數(shù)(kg/(身高(m)^2) 糖尿病系統(tǒng)功能 年齡(歲)
import pandas as pd
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
data.head()
# 導(dǎo)入工具庫
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split

# 用pandas讀入數(shù)據(jù)
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')

# 做數(shù)據(jù)切分
train, test = train_test_split(data)

# 轉(zhuǎn)換成Dmatrix格式
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'

# 取出Dataframe的numpy數(shù)組值去初始化DMatrix對象
xgtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)
xgtest = xgb.DMatrix(test[feature_columns].values, test[target_column].values)

#參數(shù)設(shè)定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }

# 設(shè)定watchlist用于查看模型狀態(tài)
watchlist  = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)

# 使用模型預(yù)測
preds = bst.predict(xgtest)

# 判斷準(zhǔn)確率
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 預(yù)估器建模方式:SKLearn接口+Dataframe

XGBoost也支持用SKLearn中統(tǒng)一的預(yù)估器形態(tài)接口進(jìn)行建模牺弄,如下為典型的參考案例姻几,對于讀取為Dataframe格式的訓(xùn)練集和測試集,可以直接使用XGBoost初始化XGBClassifier進(jìn)行fit擬合訓(xùn)練。使用方法與接口鲜棠,和SKLearn中其他預(yù)估器一致肌厨。

# 導(dǎo)入工具庫
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split

# 用pandas讀入數(shù)據(jù)
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')

# 做數(shù)據(jù)切分
train, test = train_test_split(data)

# 特征列
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
# 標(biāo)簽列
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格式數(shù)據(jù)擬合模型
xgb_classifier.fit(train[feature_columns], train[target_column])

# 使用模型預(yù)測
preds = xgb_classifier.predict(test[feature_columns])

# 判斷準(zhǔn)確率
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.模型調(diào)參與高級功能

4.1 XGBoost參數(shù)詳解

在運(yùn)行XGBoost之前,必須設(shè)置三種類型成熟:general parameters豁陆,booster parameters和task parameters:

  • 通用參數(shù):General parameters

    • 該參數(shù)控制在提升(boosting)過程中使用哪種booster柑爸,常用的booster有樹模型(tree)和線性模型(linear model)。
  • 提升器參數(shù):Booster parameters

    • 這取決于使用哪種booster盒音,包含樹模型booster和線性booster參數(shù)表鳍。
  • 任務(wù)參數(shù):Task parameters

    • 控制學(xué)習(xí)的場景,例如在回歸問題中會使用不同的參數(shù)控制排序祥诽。

(1) 通用參數(shù)

  • booster [default=gbtree]

有兩種模型可以選擇gbtree和gblinear譬圣。gbtree使用基于樹的模型進(jìn)行提升計算,gblinear使用線性模型進(jìn)行提升計算雄坪。缺省值為gbtree

  • silent [default=0]

取0時表示打印出運(yùn)行時信息厘熟,取1時表示以緘默方式運(yùn)行,不打印運(yùn)行時信息维哈。缺省值為0

  • nthread

XGBoost運(yùn)行時的線程數(shù)绳姨。缺省值是當(dāng)前系統(tǒng)可以獲得的最大線程數(shù)

  • num_pbuffer

預(yù)測緩沖區(qū)大小,通常設(shè)置為訓(xùn)練實例的數(shù)目阔挠。緩沖用于保存最后一步提升的預(yù)測結(jié)果飘庄,無需人為設(shè)置。

  • num_feature

Boosting過程中用到的特征維數(shù)购撼,設(shè)置為特征個數(shù)跪削。XGBoost會自動設(shè)置,無需人為設(shè)置迂求。

(2) 樹模型booster參數(shù)

  • eta [default=0.3]

為了防止過擬合碾盐,更新過程中用到的收縮步長。在每次提升計算之后揩局,算法會直接獲得新特征的權(quán)重廓旬。 eta通過縮減特征的權(quán)重使提升計算過程更加保守。缺省值為0.3 取值范圍為:[0,1]

  • gamma [default=0]

樹要進(jìn)一步分裂生長所需的最小loss減小值. the larger, the more conservative the algorithm will be. 取值范圍為:[0,∞]

  • max_depth [default=6]

數(shù)的最大深度谐腰。缺省值為6 取值范圍為:[1,∞]

  • min_child_weight [default=1]

孩子節(jié)點中最小的樣本權(quán)重和。如果一個葉子節(jié)點的樣本權(quán)重和小于min_child_weight則拆分過程結(jié)束涩盾。在現(xiàn)行回歸模型中十气,這個參數(shù)是指建立每個模型所需要的最小樣本數(shù)。該成熟越大算法越conservative 取值范圍為:[0,∞]

  • max_delta_step [default=0]

我們允許每個樹的權(quán)重被估計的值春霍。如果它的值被設(shè)置為0砸西,意味著沒有約束;如果它被設(shè)置為一個正值,它能夠使得更新的步驟更加保守芹枷。通常這個參數(shù)是沒有必要的衅疙,但是如果在邏輯回歸中類極其不平衡這時候他有可能會起到幫助作用。把它范圍設(shè)置為1-10之間也許能控制更新鸳慈。 取值范圍為:[0,∞]

  • subsample [default=1]

用于訓(xùn)練模型的子樣本占整個樣本集合的比例饱溢。如果設(shè)置為0.5則意味著XGBoost將隨機(jī)的從整個樣本集合中隨機(jī)的抽取出50%的子樣本建立樹模型,這能夠防止過擬合走芋。 取值范圍為:(0,1]

  • colsample_bytree [default=1]

在建立樹時對特征采樣的比例绩郎。缺省值為1 取值范圍為:(0,1]

(3) 線性Booster參數(shù)

  • lambda [default=0]

L2正則的懲罰系數(shù)

  • alpha [default=0]

L1正則的懲罰系數(shù)

  • lambda_bias

在偏置上的L2正則。缺省值為0(在L1上沒有偏置項的正則翁逞,因為L1時偏置不重要)

(4) 任務(wù)參數(shù)

  • objective [ default=reg:linear ]

    • 定義學(xué)習(xí)任務(wù)及相應(yīng)的學(xué)習(xí)目標(biāo)
    • 可選的目標(biāo)函數(shù)如下:
      • reg:linear : 線性回歸肋杖。
      • reg:logistic: 邏輯回歸。
      • binary:logistic: 二分類的邏輯回歸問題挖函,輸出為概率状植。
      • binary:logitraw: 二分類的邏輯回歸問題,輸出的結(jié)果為wTx怨喘。
      • count:poisson: 計數(shù)問題的poisson回歸津畸,輸出結(jié)果為poisson分布。在poisson回歸中哲思,max_delta_step的缺省值為0.7洼畅。(used to safeguard optimization)。
      • multi:softmax :讓XGBoost采用softmax目標(biāo)函數(shù)處理多分類問題棚赔,同時需要設(shè)置參數(shù)num_class(類別個數(shù))帝簇。
      • multi:softprob:和softmax一樣,但是輸出的是ndata * nclass的向量靠益,可以將該向量reshape成ndata行nclass列的矩陣丧肴。沒行數(shù)據(jù)表示樣本所屬于每個類別的概率。
      • rank:pairwise:set XGBoost to do ranking task by minimizing the pairwise loss胧后。
  • base_score [ default=0.5 ]

    • 所有實例的初始化預(yù)測分?jǐn)?shù)芋浮,全局偏置;
    • 為了足夠的迭代次數(shù)壳快,改變這個值將不會有太大的影響纸巷。
  • eval_metric [ default according to objective ]

    • 校驗數(shù)據(jù)所需要的評價指標(biāo),不同的目標(biāo)函數(shù)將會有缺省的評價指標(biāo)(rmse for regression, and error for classification, mean average precision for ranking)
    • 用戶可以添加多種評價指標(biāo)眶痰,對于Python用戶要以list傳遞參數(shù)對給程序瘤旨,而不是map參數(shù)list參數(shù)不會覆蓋`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 ]

    • 隨機(jī)數(shù)的種子。缺省值為0

4.2 內(nèi)置調(diào)參優(yōu)化

(1) 交叉驗證

XGBoost自帶實驗與調(diào)參的一些方法竖伯,如下為交叉驗證方法xgb.cv存哲。

xgb.cv(param, dtrain, num_round, nfold=5,metrics={'error'}, seed = 0)

(2) 添加預(yù)處理

我們可以把數(shù)據(jù)建模過程中的一些設(shè)置加到交叉驗證環(huán)節(jié)里因宇,比如對于不同類別的樣本加權(quán),可以參考下列代碼示例

# 計算正負(fù)樣本比祟偷,調(diào)整樣本權(quán)重
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)

# 先做預(yù)處理察滑,計算樣本權(quán)重,再做交叉驗證
xgb.cv(param, dtrain, num_round, nfold=5,
       metrics={'auc'}, seed = 0, fpreproc = fpreproc)

(3) 自定義損失函數(shù)與評估準(zhǔn)則

XGBoost支持在訓(xùn)練過程中修肠,自定義損失函數(shù)和評估準(zhǔn)則贺辰,其中損失函數(shù)的定義需要返回?fù)p失函數(shù)一階和二階導(dǎo)數(shù)的計算方法,評估準(zhǔn)則部分需要對數(shù)據(jù)的label和預(yù)估值進(jìn)行計算氛赐。其中損失函數(shù)用于訓(xùn)練過程中的樹結(jié)構(gòu)學(xué)習(xí)魂爪,而評估準(zhǔn)則很多時候是用在驗證集上進(jìn)行效果評估。

print('使用自定義損失函數(shù)進(jìn)行交叉驗證')
# 自定義損失函數(shù)艰管,需要提供損失函數(shù)的一階導(dǎo)和二階導(dǎo)
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

# 自定義評估準(zhǔn)則滓侍,評估預(yù)估值和標(biāo)準(zhǔn)答案之間的差距
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
# 自定義損失函數(shù)訓(xùn)練
bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
# 交叉驗證
xgb.cv(param, dtrain, num_round, nfold = 5, seed = 0, obj = logregobj, feval=evalerror)
使用自定義損失函數(shù)進(jìn)行交叉驗證
[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顆樹預(yù)測

對于boosting模型來說,最后會訓(xùn)練得到很多基學(xué)習(xí)器(在XGBoost中很多時候是很多棵樹)牲芋,我們可以一次完整訓(xùn)練撩笆,只用前n棵樹的集成來完成預(yù)測。

#!/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文件中讀取數(shù)據(jù)夕冲,做二分類

# 用pandas讀入數(shù)據(jù)
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')

# 做數(shù)據(jù)切分
train, test = train_test_split(data)

# 轉(zhuǎn)換成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)

#參數(shù)設(shè)定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }

# 設(shè)定watchlist用于查看模型狀態(tài)
watchlist  = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)

# 只用第1顆樹預(yù)測
ypred1 = bst.predict(xgtest, ntree_limit=1)
# 用前9顆樹預(yù)測
ypred2 = bst.predict(xgtest, ntree_limit=9)
label = xgtest.get_label()
print('用前1顆樹預(yù)測的錯誤率為 %f' % (np.sum((ypred1>0.5)!=label) /float(len(label))))
print('用前9顆樹預(yù)測的錯誤率為 %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顆樹預(yù)測的錯誤率為 0.255208
用前9顆樹預(yù)測的錯誤率為 0.187500

4.3 預(yù)估器調(diào)參優(yōu)化

(1) SKLearn形態(tài)接口實驗評估

XGBoost有SKLearn預(yù)估器形態(tài)的接口,整體使用方法和SKLearn中其他預(yù)估器一致裂逐,如下是手動對數(shù)據(jù)做交叉驗證歹鱼,注意到這里直接使用XGBClassifier對Dataframe數(shù)據(jù)進(jìn)行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("數(shù)字0和1的二分類問題")
digits = load_digits(2)
y = digits['target']
X = digits['data']
# 數(shù)據(jù)切分對象
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折數(shù)據(jù)上的交叉驗證")
# 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折數(shù)據(jù)上的交叉驗證")
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波士頓房價回歸預(yù)測問題")
boston = load_boston()
y = boston['target']
X = boston['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折數(shù)據(jù)上的交叉驗證")
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))
數(shù)字0和1的二分類問題
在2折數(shù)據(jù)上的交叉驗證
混淆矩陣:
[[87  0]
 [ 1 92]]
混淆矩陣:
[[91  0]
 [ 3 86]]

Iris: 多分類
在2折數(shù)據(jù)上的交叉驗證
混淆矩陣:
[[19  0  0]
 [ 0 31  3]
 [ 0  1 21]]
混淆矩陣:
[[31  0  0]
 [ 0 16  0]
 [ 0  3 25]]

波士頓房價回歸預(yù)測問題
在2折數(shù)據(jù)上的交叉驗證
MSE: 9.860776812557337
MSE: 15.942418468446029

(2) 網(wǎng)格搜索調(diào)參

上面提到XGBoost的預(yù)估器接口卜高,整體使用方法和SKLearn中其他預(yù)估器一致弥姻,所以我們也可以使用SKLearn中的超參數(shù)調(diào)優(yōu)方法來進(jìn)行模型調(diào)優(yōu)。

如下是一個典型的網(wǎng)格搜索交法調(diào)優(yōu)超參數(shù)的代碼示例掺涛,我們會給出候選參數(shù)列表字典庭敦,通過GridSearchCV進(jìn)行交叉驗證實驗評估,選出XGBoost在候選參數(shù)中最優(yōu)的超參數(shù)薪缆。
print("參數(shù)最優(yōu)化:")

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_)
參數(shù)最優(yōu)化:
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模型有時候會因為不停疊加新的樹(修正訓(xùn)練集上擬合尚不正確的一些樣本)秧廉,可能會因為對于訓(xùn)練集過度學(xué)習(xí)而導(dǎo)致模型過擬合。early stopping早停止是一個有效的策略拣帽,具體的做法是疼电,在訓(xùn)練集不斷追加樹學(xué)習(xí)的過程中,對驗證集上的表現(xiàn)進(jìn)行監(jiān)控减拭,如果出現(xiàn)一定輪次評估準(zhǔn)則都沒有優(yōu)化提升的情況澜沟,則回溯到歷史上驗證集最好的點,保存為最佳模型峡谊。

下面是對應(yīng)的代碼示例,其中參數(shù)early_stopping_rounds設(shè)定了驗證集上能接受的效果不提升的最多輪次數(shù),eval_set指定了驗證數(shù)據(jù)集既们。

# 在訓(xùn)練集上學(xué)習(xí)模型濒析,一顆一顆樹添加,在驗證集上看效果啥纸,當(dāng)驗證集效果不再提升号杏,停止樹的添加與生長
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建模過程中,還可以學(xué)習(xí)到對應(yīng)的特征重要度信息斯棒,并保存在模型的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) 并行訓(xùn)練加速

在多資源的情況下,XGBoost可以實現(xiàn)并行訓(xùn)練加速荣暮,示例代碼如下:

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
教程地址http://www.showmeai.tech/tutorials/41
本文地址http://www.showmeai.tech/article-detail/204
聲明:版權(quán)所有庭惜,轉(zhuǎn)載請聯(lián)系平臺與作者并注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市穗酥,隨后出現(xiàn)的幾起案子护赊,更是在濱河造成了極大的恐慌,老刑警劉巖砾跃,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骏啰,死亡現(xiàn)場離奇詭異,居然都是意外死亡抽高,警方通過查閱死者的電腦和手機(jī)判耕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翘骂,“玉大人壁熄,你說我怎么就攤上這事〕福” “怎么了请毛?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞭亮。 經(jīng)常有香客問我方仿,道長,這世上最難降的妖魔是什么统翩? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任仙蚜,我火速辦了婚禮,結(jié)果婚禮上厂汗,老公的妹妹穿的比我還像新娘委粉。我一直安慰自己,他們只是感情好娶桦,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布贾节。 她就那樣靜靜地躺著汁汗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栗涂。 梳的紋絲不亂的頭發(fā)上知牌,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音斤程,去河邊找鬼角寸。 笑死,一個胖子當(dāng)著我的面吹牛忿墅,可吹牛的內(nèi)容都是我干的扁藕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼疚脐,長吁一口氣:“原來是場噩夢啊……” “哼亿柑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亮曹,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤橄杨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后照卦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體式矫,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年役耕,在試婚紗的時候發(fā)現(xiàn)自己被綠了采转。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞬痘,死狀恐怖故慈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情框全,我是刑警寧澤察绷,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站津辩,受9級特大地震影響拆撼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喘沿,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一闸度、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚜印,春花似錦莺禁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楼熄。三九已至,卻和暖如春浩峡,著一層夾襖步出監(jiān)牢的瞬間孝赫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工红符, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伐债。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓预侯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親峰锁。 傳聞我的和親對象是個殘疾皇子萎馅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345