我在探索R语言中的xgboost
包,并查看了几个演示和教程,但这仍然让我感到困惑:在使用xgb.cv
进行交叉验证后,最优参数是如何传递给xgb.train
的?或者我应该根据xgb.cv
的输出计算理想参数(如nround
、max.depth
)吗?
param <- list("objective" = "multi:softprob", "eval_metric" = "mlogloss", "num_class" = 12)cv.nround <- 11cv.nfold <- 5mdcv <-xgb.cv(data=dtrain,params = param,nthread=6,nfold = cv.nfold,nrounds = cv.nround,verbose = T)md <-xgb.train(data=dtrain,params = param,nround = 80,watchlist = list(train=dtrain,test=dtest),nthread=6)
回答:
看起来你误解了xgb.cv
,它不是一个参数搜索函数。它只是进行k折交叉验证,仅此而已。
在你的代码中,它不会改变param
的值。
要在R的XGBoost中找到最佳参数,有一些方法。这里有两种方法,
(1) 使用mlr
包,http://mlr-org.github.io/mlr-tutorial/release/html/
在Kaggle的Prudential挑战中,有一个XGBoost + mlr的示例代码,
但那个代码是用于回归的,不是分类。据我所知,mlr
包中还没有mlogloss
指标,所以你必须自己从头开始编写mlogloss测量。CMIIW。
(2) 第二种方法,通过手动设置参数然后重复,例如,
param <- list(objective = "multi:softprob", eval_metric = "mlogloss", num_class = 12, max_depth = 8, eta = 0.05, gamma = 0.01, subsample = 0.9, colsample_bytree = 0.8, min_child_weight = 4, max_delta_step = 1 )cv.nround = 1000cv.nfold = 5mdcv <- xgb.cv(data=dtrain, params = param, nthread=6, nfold=cv.nfold, nrounds=cv.nround, verbose = T)
然后,你找到最佳(最小)的mlogloss,
min_logloss = min(mdcv[, test.mlogloss.mean])min_logloss_index = which.min(mdcv[, test.mlogloss.mean])
min_logloss
是mlogloss的最小值,而min_logloss_index
是索引(轮次)。
你必须重复上述过程几次,每次手动更改参数(mlr
会为你重复)。直到最后你得到最佳的全局最小min_logloss
。
注意: 你可以在100或200次迭代的循环中进行,每次迭代随机设置参数值。这样,你必须将最佳的[parameters_list, min_logloss, min_logloss_index]
保存到变量或文件中。
注意: 最好通过set.seed()
设置随机种子以获得可重现的结果。不同的随机种子会产生不同的结果。因此,你必须将[parameters_list, min_logloss, min_logloss_index, seednumber]
保存到变量或文件中。
假设最后你在3次迭代/重复中得到了3个结果:
min_logloss = 2.1457, min_logloss_index = 840min_logloss = 2.2293, min_logloss_index = 920min_logloss = 1.9745, min_logloss_index = 780
那么你必须使用第三组参数(它具有全局最小min_logloss
值1.9745
)。你最佳的索引(nrounds)是780
。
一旦你得到最佳参数,就在训练中使用它,
# best_param 是具有最小 min_logloss 的全局最佳参数# best_min_logloss_index 是全局最小 logloss 索引nround = 780md <- xgb.train(data=dtrain, params=best_param, nrounds=nround, nthread=6)
我认为在训练中你不需要watchlist
,因为你已经完成了交叉验证。但如果你仍然想使用watchlist
,那也没问题。
更好的做法是可以在xgb.cv
中使用早停机制。
mdcv <- xgb.cv(data=dtrain, params=param, nthread=6, nfold=cv.nfold, nrounds=cv.nround, verbose = T, early.stop.round=8, maximize=FALSE)
使用这段代码,当mlogloss
值在8个步骤内没有减少时,xgb.cv
将停止。你可以节省时间。你必须将maximize
设置为FALSE
,因为你期望最小化mlogloss。
这里有一个示例代码,包含100次迭代循环,并随机选择参数。
best_param = list()best_seednumber = 1234best_logloss = Infbest_logloss_index = 0for (iter in 1:100) { param <- list(objective = "multi:softprob", eval_metric = "mlogloss", num_class = 12, max_depth = sample(6:10, 1), eta = runif(1, .01, .3), gamma = runif(1, 0.0, 0.2), subsample = runif(1, .6, .9), colsample_bytree = runif(1, .5, .8), min_child_weight = sample(1:40, 1), max_delta_step = sample(1:10, 1) ) cv.nround = 1000 cv.nfold = 5 seed.number = sample.int(10000, 1)[[1]] set.seed(seed.number) mdcv <- xgb.cv(data=dtrain, params = param, nthread=6, nfold=cv.nfold, nrounds=cv.nround, verbose = T, early.stop.round=8, maximize=FALSE) min_logloss = min(mdcv[, test.mlogloss.mean]) min_logloss_index = which.min(mdcv[, test.mlogloss.mean]) if (min_logloss < best_logloss) { best_logloss = min_logloss best_logloss_index = min_logloss_index best_seednumber = seed.number best_param = param }}nround = best_logloss_indexset.seed(best_seednumber)md <- xgb.train(data=dtrain, params=best_param, nrounds=nround, nthread=6)
使用这段代码,你将进行100次交叉验证,每次使用随机参数。然后你得到最佳参数集,即在最小min_logloss
的迭代中得到的参数集。
如果发现early.stop.round
的值太小(停止得太早),可以增加它的值。你还需要根据数据特征调整随机参数值的范围。
对于100或200次迭代,我认为你可能想将verbose
设置为FALSE。
补充说明: 这是随机方法的一个例子,你可以调整它,例如通过贝叶斯优化来获得更好的方法。如果你有Python版本的XGBoost,有一个很好的超参数脚本用于XGBoost,https://github.com/mpearmain/BayesBoost,用于使用贝叶斯优化搜索最佳参数集。
编辑:我想添加第三种手动方法,由Kaggle大师”Davut Polat”在Kaggle论坛中发布。
编辑:如果你熟悉Python和sklearn,你也可以使用GridSearchCV以及xgboost.XGBClassifier或xgboost.XGBRegressor