在Hyperopt框架下使用XGboost与交叉验证
Hyperopttutorials:Xgboost+CVHyperopt \ tutorials: Xgboost + CVHyperopt?tutorials:Xgboost+CV
前言
Xgboost中內置了交叉驗證,如果我們需要在Hyperopt中使用交叉驗證的話,只需要直接調用即可。前邊我們依舊采用第一篇教程使用過的代碼。如果你已經看過前一篇文章,那么我建議你直接跳到交叉驗證部分。
與第一篇教程-如何使用hyperopt對xgboost進行自動調參相同的是,本處教程中的代碼也可以很好的被套用。并且可以很好的遷移到lightgbm與catboost上面。源代碼請前往Github教程地址下載下載。
加載數據
讀取數據并分割
因為我們這里使用的是交叉驗證因此我們也就不再需要,將數據集分割為三份了,只需要分割出百分之十的數據用于預測就好。注意隨機數的問題。
from hyperopt import fmin, tpe, hp, partial import numpy as np from sklearn.model_selection import train_test_split, cross_val_score from sklearn.metrics import mean_squared_error, zero_one_loss import xgboost as xgb import pandas as pddef GetNewDataByPandas():wine = pd.read_csv("../data/wine.csv")wine['alcohol**2'] = pow(wine["alcohol"], 2)wine['volatileAcidity*alcohol'] = wine["alcohol"] * wine['volatile acidity']y = np.array(wine.quality)X = np.array(wine.drop("quality", axis=1))columns = np.array(wine.columns)return X, y, columns分割數據并轉換
首先將數據分割為三份,一部分用于預測,訓練數據則同樣分成額外的兩部分用于evallist參數。
同時為了加快速度和減少內存,我們將數據轉換為xgboost自帶的讀取格式。
# Read wine quality data from file X, y, wineNames = GetNewDataByPandas()# split data to [[0.8,0.2],01] x_train_all, x_predict, y_train_all, y_predict = train_test_split(X, y, test_size=0.10, random_state=100)x_train, x_test, y_train, y_test = train_test_split(x_train_all, y_train_all, test_size=0.2, random_state=100)dtrain = xgb.DMatrix(data=x_train,label=y_train,missing=-999.0) dtest = xgb.DMatrix(data=x_test,label=y_test,missing=-999.0)evallist = [(dtest, 'eval'), (dtrain, 'train')]利用交叉驗證訓練
訓練模型
在之前的代碼中,我將數據分割為 6:3:1,其分別為,訓練數據,性能監視用數據,和最后的預測數據。這個比例只是為了示例用,并不具有代表性。
本處則主要介紹交叉驗證方法。
交叉驗證與Hyperopt結合
xgboost進行交叉驗證與Hyperopt結合有兩種方案,第一種方案是使用本身自帶的CV方法,但是這種方案的存在一個問題,就是CV中無法直接傳遞分開的參數,而只能傳遞唯一參數params,因此我們需要先生成一個model,然后通過get_params()來獲取參數,這種方式代碼會稍微多幾行。不過相較于與sklearn結合的形式,計算時間上則有很大的提升。
第二種方案:也可以直接使用sklearn.model_selection中的多種交叉驗證方案,只將xgboost作為單個模型傳入。但是個人并不建議這樣做。首先是和sklearn的交互會一定程度上導致計算性能的下降,而且計算時間上差距可能會很大。所以個人建議只有在必要的時候,可以采用最傳統的train_test_split方案時使用類似的代碼結構,但是還是不適用和sklearn結合形式的交叉驗證,具體怎么做會在其他例子中介紹。
使用CV方法進行交叉驗證
直接使用xgboost中的cv方法進行交叉驗證應該是最好的方案。唯一的問題是如何傳入唯一的params參數。不知道為什么在我翻譯玩hyperopt中文文檔的這近一年,都沒有見到有人寫這一類的。有可能是沒想到如何解決吧這個問題吧。
import hyperoptdef hyperopt_objective(params):model = xgb.XGBRegressor(max_depth=int(params['max_depth'])+5,learning_rate=params['learning_rate'],silent=1,objective='reg:linear',eval_metric='rmse',seed=619,nthread=-1,)res = xgb.cv(model.get_params(), dtrain, num_boost_round=10, nfold=5,callbacks=[xgb.callback.print_evaluation(show_stdv=False),xgb.callback.early_stop(3)])return np.min(res['test-rmse-mean']) # as hyperopt minimises from numpy.random import RandomStateparams_space = {'max_depth': hyperopt.hp.randint('max_depth', 6),'learning_rate': hyperopt.hp.uniform('learning_rate', 1e-3, 5e-1), }trials = hyperopt.Trials()best = hyperopt.fmin(hyperopt_objective,space=params_space,algo=hyperopt.tpe.suggest,max_evals=50,trials=trials,rstate=RandomState(123) )print("\n展示hyperopt獲取的最佳結果,但是要注意的是我們對hyperopt最初的取值范圍做過一次轉換") print(best) [0] train-rmse:3.24774 test-rmse:3.24823 Multiple eval metrics have been passed: 'test-rmse' will be used for early stopping.Will train until test-rmse hasn't improved in 3 rounds. [1] train-rmse:2.07359 test-rmse:2.0891 [2] train-rmse:1.36012 test-rmse:1.40987 [3] train-rmse:0.928331 test-rmse:1.02378 [4] train-rmse:0.657333 test-rmse:0.827554 [5] train-rmse:0.488443 test-rmse:0.732572 [6] train-rmse:0.382361 test-rmse:0.690592 [7] train-rmse:0.310456 test-rmse:0.669706 [8] train-rmse:0.257609 test-rmse:0.661822 [9] train-rmse:0.216769 test-rmse:0.657073 [0] train-rmse:3.09603 test-rmse:3.09669 Multiple eval metrics have been passed: 'test-rmse' will be used for early stopping....[5] train-rmse:0.511304 test-rmse:0.670014 [6] train-rmse:0.473608 test-rmse:0.65754 [7] train-rmse:0.450189 test-rmse:0.647339 [8] train-rmse:0.428634 test-rmse:0.642954 [9] train-rmse:0.410831 test-rmse:0.64032展示hyperopt獲取的最佳結果,但是要注意的是我們對hyperopt最初的取值范圍做過一次轉換 {'learning_rate': 0.44307009444016143, 'max_depth': 0}使用sklearn進行交叉驗證
這里要注意的是運算速度上也是有一定差距的。而且可能很大。本例運行于我個人的筆記本(i7-5500u,Ubuntu18.04)時候,與sklearn結合的方案用時約是完全使用xgboost的3-6倍,而在我的另外一個系統上(i7-8750H,windows10),與sklearn結合的版本則只是xgboost的45%的運行時間。計算時間差異,也可能是由數據集的大小和硬件等多種原因造成的,因此具體情況建議自行實驗。我在這里也很難給出一個較準確的答案。
def XGBRegressor_CV(params):from sklearn.model_selection import cross_val_scoremodel = xgb.XGBRegressor(max_depth=int(params['max_depth'])+5,learning_rate=params['learning_rate'],silent=1,objective='reg:linear',eval_metric='rmse',seed=619,nthread=-1,early_stopping_rounds=3)# x_train, x_predict, y_train, y_predictmetric = cross_val_score(model, x_train, y_train, cv=5, scoring="neg_mean_squared_error")return min(-metric) trials_2 = hyperopt.Trials()best_2 = hyperopt.fmin(XGBRegressor_CV,space=params_space,algo=hyperopt.tpe.suggest,max_evals=50,trials=trials_2,rstate=RandomState(123) )print("\n展示hyperopt獲取的最佳結果,但是要注意的是我們對hyperopt最初的取值范圍做過一次轉換") print(best_2) 展示hyperopt獲取的最佳結果,但是要注意的是我們對hyperopt最初的取值范圍做過一次轉換 {'learning_rate': 0.06047936704428278, 'max_depth': 4}總結
以上是生活随笔為你收集整理的在Hyperopt框架下使用XGboost与交叉验证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用hyperopt对xgboost
- 下一篇: 在Python中使用XGBoost