【问题标题】:Combining train + test data and running cross validation in R结合训练+测试数据并在R中运行交叉验证
【发布时间】:2018-02-28 19:31:15
【问题描述】:

我有以下 R 代码,它在一组训练和测试数据上运行一个简单的 xgboost 模型,目的是预测二元结果。

我们从

开始

1) 阅读相关库。

library(xgboost)
library(readr)
library(caret)

2) 清理训练和测试数据

train.raw = read.csv("train_data", header = TRUE, sep = ",")
drop = c('column')
train.df = train.raw[, !(names(train.raw) %in% drop)]
train.df[,'outcome'] = as.factor(train.df[,'outcome'])


test.raw = read.csv("test_data", header = TRUE, sep = ",")
drop = c('column')
test.df = test.raw[, !(names(test.raw) %in% drop)]
test.df[,'outcome'] = as.factor(test.df[,'outcome'])

train.c1 = subset(train.df ,  outcome == 1)
train.c0 = subset(train.df ,  outcome == 0)

3) 对格式正确的数据运行 XGBoost。

train_xgb = xgb.DMatrix(data.matrix(train.df [,1:124]), label = train.raw[, "outcome"])
test_xgb = xgb.DMatrix(data.matrix(test.df[,1:124])) 

4) 运行模型

model_xgb = xgboost(data = train_xgb, nrounds = 8, max_depth = 5, eta = .1, eval_metric = "logloss", objective = "binary:logistic", verbose = 5)

5) 做出预测

pred_xgb <- predict(model_xgb, newdata = test_xgb)

我的问题是:我如何调整这个过程,以便我只是拉入/调整一个“训练”数据集,并获得对交叉验证文件的保留集的预测?

【问题讨论】:

  • 尝试在xgboost 调用中添加nfold = 5 以进行5 倍CV。此外,您应该指定更多轮次,可能是 1000 轮左右。如果您这样做,print_every_n = 100 是一个受欢迎的论点。一般来说,如果你指定测试集,你会做验证,如果你指定 nfold,你会做 k-fold CV。
  • @missuse 抱歉,我意识到我的问题不是很清楚,不过您的回答很有帮助。我真正想要了解的是如何对仅包含训练数据的 10 倍交叉验证数据集的保留集进行预测。
  • 对不起,我搞错了,要指定k-fold CV,需要调用xgb.cv函数。在这里您可以指定prediction = TRUE,您将对每个折叠进行预测:model$pred - 它们的顺序与您的火车组中的顺序相同。折叠在model$folds 中指定。在 xgb.cv 之前设置种子将选择相同的折叠但不同的模型,要重现相同的模型,需要在 xgb.cv 调用中设置 seed
  • @missuse 谢谢,那么我是否可以简单地将 xgboost 替换为 xgb.cv 并添加 prediction = TRUE 作为参数?我还需要调整什么才能使其正常工作吗?
  • 是的,xgb.cv(nfold = 10, prediction = TRUE, seed = 123...) else as in xgboost call

标签: r machine-learning


【解决方案1】:

要在 xgboost 调用中指定 k-fold CV,需要使用 nfold = some integer 参数调用 xgb.cv,以保存每个重新采样的预测,使用 prediction = TRUE 参数。例如:

xgboostModelCV <- xgb.cv(data = dtrain, 
                         nrounds =  1688,
                         nfold = 5,
                         objective = "binary:logistic",
                         eval_metric= "auc",
                         metrics = "auc",
                         verbose = 1,
                         print_every_n = 50,
                         stratified = T,
                         scale_pos_weight = 2
                         max_depth = 6, 
                         eta = 0.01, 
                         gamma=0,
                         colsample_bytree =  1 ,
                         min_child_weight = 1,
                         subsample=  0.5 ,
                         prediction = T)

xgboostModelCV$pred #contains predictions in the same order as in dtrain.
xgboostModelCV$folds #contains k-fold samples

这是一个不错的选择超参数的函数

function(train, seed){
  require(xgboost)
  ntrees=2000
  searchGridSubCol <- expand.grid(subsample = c(0.5, 0.75, 1), 
                                  colsample_bytree = c(0.6, 0.8, 1),
                                  gamma=c(0, 1, 2),
                                  eta=c(0.01, 0.03),
                                  max_depth=c(4,6,8,10))
  aucErrorsHyperparameters <- apply(searchGridSubCol, 1, function(parameterList){

    #Extract Parameters to test
    currentSubsampleRate <- parameterList[["subsample"]]
    currentColsampleRate <- parameterList[["colsample_bytree"]]
    currentGamma <- parameterList[["gamma"]]
    currentEta =parameterList[["eta"]]
    currentMaxDepth =parameterList[["max_depth"]]
    set.seed(seed)

    xgboostModelCV <- xgb.cv(data = train, 
                             nrounds = ntrees,
                             nfold = 5,
                             objective = "binary:logistic",
                             eval_metric= "auc",
                             metrics = "auc",
                             verbose = 1,
                             print_every_n = 50,
                             early_stopping_rounds = 200,
                             stratified = T,
                             scale_pos_weight=sum(all_data_nobad[index_no_bad,1]==0)/sum(all_data_nobad[index_no_bad,1]==1),
                             max_depth = currentMaxDepth, 
                             eta = currentEta, 
                             gamma=currentGamma,
                             colsample_bytree = currentColsampleRate,
                             min_child_weight = 1,
                             subsample=  currentSubsampleRate) 


    xvalidationScores <- as.data.frame(xgboostModelCV$evaluation_log)
    #Save rmse of the last iteration
    auc=xvalidationScores[xvalidationScores$iter==xgboostModelCV$best_iteration,c(1,4,5)]
    auc=cbind(auc, currentSubsampleRate, currentColsampleRate, currentGamma, currentEta,  currentMaxDepth)
    names(auc)=c("iter", "test.auc.mean", "test.auc.std", "subsample", "colsample", "gamma", "eta", "max.depth")
    print(auc)
    return(auc)
  })
  return(aucErrorsHyperparameters)
}

您可以更改网格值和网格中的参数,以及损失/评估指标。它与caret 网格搜索提供的类似,但caret 不提供定义alphalambdacolsample_bylevelnum_parallel_tree... 网格搜索中的超参数的可能性,除了定义一个我觉得很麻烦的自定义功能。 Caret具有自动预处理、CV内自动上/下采样等优点。

在 xgb.cv 调用之外设置种子将为 CV 选择相同的折叠,但在每一轮中不会选择相同的树,因此您最终会得到不同的模型。即使您在 xgb.cv 函数调用中设置种子,也不能保证您最终会得到相同的模型,但机会更高(取决于线程、模型的类型..-我喜欢不确定性并发现对结果影响不大)。

【讨论】:

  • 感谢选择超参数的功能特别有用。更简单地说,现在我打印到带有write.table(prob[, pred], "file") 之类的表格,我可以用write.table(xgboostModelCV$pred) 来达到同样的效果吗?
  • 可以,试试看,还可以构造混淆矩阵,ROC,提升曲线,确定模型的概率阈值(二分类问题的model$pred其实包含的概率是某一类)。对于这些,您需要提供真正的 label,就像您在 xgb.DMatrix(data.matrix(train.df [,1:124]), label = train.raw[, "outcome"]) 中所做的那样
  • 谢谢,例如:write.table(myModel$pred[, c("name", "xgb")], " file", sep = ",", row.names = FALSE, col.names = c("name", "outcome"))
【解决方案2】:

您可以使用 xgb.cv 并设置 prediction = TRUE。

【讨论】:

  • 抱歉,您能详细说明一下吗?
猜你喜欢
  • 2011-12-16
  • 2020-09-14
  • 2018-05-03
  • 2016-01-29
  • 2020-03-13
  • 2014-05-01
  • 2021-12-10
  • 2021-03-04
  • 2020-12-15
相关资源
最近更新 更多