种子对象,用于在插入符号中并行操作的可重现结果

时间:2015-08-19 15:38:10

标签: r r-caret

我正在尝试将代码用于插入符号中完全可重现的并行模型,但不了解如何设置种子对象中向量的大小。对于gbm,我有4个调整参数,共有11个不同的级别,我的调优网格中有54行。如果我指定任何值< 18作为" for(i in 1:10)"中的最后一个值在下面的行中,我得到一个错误:"坏种子:种子对象应该是长度为11的列表,其中10个整数向量大小为18,最后一个列表元素具有单个整数。"为什么18?它也可以在没有错误的情况下运行> 18(例如54) - 为什么?非常感谢您的帮助。以下内容基于http://topepo.github.io/caret/training.html,添加了一些内容。

library(mlbench)
data(Sonar)
str(Sonar[, 1:10])
library(caret)
library(doParallel)

set.seed(998)
inTraining <- createDataPartition(Sonar$Class, p = .75, list = FALSE)
training <- Sonar[ inTraining,]
testing  <- Sonar[-inTraining,]

grid <- expand.grid(n.trees = seq(50,150,by=50), interaction.depth = seq(1,3,by=1),
  shrinkage = seq(.09,.11,by=.01),n.minobsinnode=seq(8,10,by=2)) 

# set seed to run fully reproducible model in parallel mode using caret          
set.seed(825)
seeds <- vector(mode = "list", length = 11) # length is = (n_repeats*nresampling)+1
for(i in 1:10) seeds[[i]]<- sample.int(n=1000, 11) # ...the number of tuning parameter...
seeds[[11]]<-sample.int(1000, 1) # for the last model

fitControl <- trainControl(method = "cv",number = 10,seeds=seeds)               

# run model in parallel
cl <- makeCluster(detectCores())
registerDoParallel(cl)

gbmFit1 <- train(Class ~ ., data = training,method = "gbm",
  trControl = fitControl,tuneGrid=grid,verbose = FALSE)
gbmFit1

1 个答案:

答案 0 :(得分:5)

我将分两部分解答您的问题:

1 - 设置seeds

按照你的说法执行此操作的代码:

set.seed(825)
seeds <- vector(mode = "list", length = 11)
for(i in 1:10) seeds[[i]]<- sample.int(n=1000, 54)
#for the last model
seeds[[11]]<-sample.int(1000, 1)

11中的seeds <- vector(mode = "list", length = 11)(n_repeats*nresampling)+1,因此,在您的情况下,您使用10-fold CV10+1 = 11。如果您将repeatedcvnumber=10 and repeats = 5一起使用,则会将11替换为(5*10)+1 = 51

10中的for(i in 1:10)(n_repeats*nresampling)。在您的情况下,它是10,因为您正在使用10-fold CV。同样,如果您将repeatedcvnumber=10 and repeats = 5一起使用,则会for(i in 1:50)

54中的sample.int(n=1000, 54)number of tuning parameter combinations。在您的情况下,4 parameters3,3,3 and 2 values。所以,它是3*3*3*2 = 54但是,我记得我在某个地方红色,对于gbm,模型适合网格中的max(n.trees),并且从中得到树数较少的模型,这解释了为什么caret计算seeds基于您的interaction.depth * shrinkage * n.minobsinnode 3 * 3 * 2 = 18而不是3*3*3*2 = 54,我们稍后会看到。

但是,如果您使用的网格为SVM的{​​{1}}模型,那么您的值为svmGrid <- expand.grid(sigma= 2^c(-25, -20, -15,-10, -5, 0), C= 2^c(0:5))

请注意,使用6 * 6 = 36的目的是通过为每个重新采样迭代设置适合的模型的种子来允许seeds

reproducible research用于设置适合整个数据集的最后(最佳)模型的种子。

2 - 如果指定值&lt;为什么会出现错误? 18,但没有值为&gt; = 18

的错误

我能够在我的机器上重现相同的错误:

seeds[[11]]<-sample.int(1000, 1)

因此,通过检查Error in train.default(x, y, weights = w, ...) : Bad seeds: the seed object should be a list of length 11 with 10 integer vectors of size 18 and the last list element having a single integer 我能够找到它的来源。根据行train.defaultstop中的测试7 to 10,行badSeed中的4会触发错误消息。

5

else { if (!(length(trControl$seeds) == 1 && is.na(trControl$seeds))) { numSeeds <- unlist(lapply(trControl$seeds, length)) 4 badSeed <- (length(trControl$seeds) < length(trControl$index) + 5 1) || (any(numSeeds[-length(numSeeds)] < nrow(trainInfo$loop))) if (badSeed) 7 stop(paste("Bad seeds: the seed object should be a list of length", 8 length(trControl$index) + 1, "with", length(trControl$index), 9 "integer vectors of size", nrow(trainInfo$loop), 10 "and the last list element having a", "single integer")) } } 号来自18,因此我们需要找到nrow(trainInfo$loop)的值。对象trainInfo$loop在第3行中分配了值trainInfo

trainInfo <- models$loop(tuneGrid)

现在,我们需要找到对象 if (trControl$method != "none") { if (is.function(models$loop) && nrow(tuneGrid) > 1) { 3 trainInfo <- models$loop(tuneGrid) if (!all(c("loop", "submodels") %in% names(trainInfo))) stop("The 'loop' function should produce a list with elements 'loop' and 'submodels'") } 。它在第2行中被赋予models的值:

models <- getModelInfo(method, regex = FALSE)[[1]]

由于我们使用 else { 2 models <- getModelInfo(method, regex = FALSE)[[1]] if (length(models) == 0) stop(paste("Model", method, "is not in caret's built-in library")) } ,我们可以看到method = "gbm"的值并检查以下结果:

getModelInfo("gbm", regex = FALSE)[[1]]$loop

> getModelInfo("gbm", regex = FALSE)[[1]]$loop function(grid) { 3 loop <- ddply(grid, c("shrinkage", "interaction.depth", "n.minobsinnode"), function(x) c(n.trees = max(x$n.trees))) submodels <- vector(mode = "list", length = nrow(loop)) for(i in seq(along = loop$n.trees)) { index <- which(grid$interaction.depth == loop$interaction.depth[i] & grid$shrinkage == loop$shrinkage[i] & grid$n.minobsinnode == loop$n.minobsinnode[i]) trees <- grid[index, "n.trees"] submodels[[i]] <- data.frame(n.trees = trees[trees != loop$n.trees[i]]) } list(loop = loop, submodels = submodels) } > (在第3行中)被赋值:

loop

现在,让我们将loop <- ddply(grid, c("shrinkage", "interaction.depth", "n.minobsinnode"), function(x) c(n.trees = max(x$n.trees)))` grid一起传递到上面一行并检查结果:

54 rows

啊!我们找到了。值> nrow(grid) [1] 54 > > loop <- ddply(grid, c("shrinkage", "interaction.depth", "n.minobsinnode"), + function(x) c(n.trees = max(x$n.trees))) > loop shrinkage interaction.depth n.minobsinnode n.trees 1 0.09 1 8 150 2 0.09 1 10 150 3 0.09 2 8 150 4 0.09 2 10 150 5 0.09 3 8 150 6 0.09 3 10 150 7 0.10 1 8 150 8 0.10 1 10 150 9 0.10 2 8 150 10 0.10 2 10 150 11 0.10 3 8 150 12 0.10 3 10 150 13 0.11 1 8 150 14 0.11 1 10 150 15 0.11 2 8 150 16 0.11 2 10 150 17 0.11 3 8 150 18 0.11 3 10 150 > 来自18,来自上面显示的nrow(trainInfo$loop)只有getModelInfo("gbm", regex = FALSE)[[1]]$loop

现在,回到触发错误的测试:

18 rows

测试的第一部分badSeed <- (length(trControl$seeds) < length(trControl$index) + 1) || (any(numSeeds[-length(numSeeds)] < nrow(trainInfo$loop))) (length(trControl$seeds) < length(trControl$index) + 1),但第二部分FALSE(any(numSeeds[-length(numSeeds)] < nrow(trainInfo$loop))),所有值均为TRUE来自18所有值大于nrow(trainInfo$loop)的{​​1}}和FALSE。这就是为18而不是<18触发错误的原因。如上所述,插入符号会根据您>=18中的seeds计算interaction.depth * shrinkage * n.minobsinnode(模型适合3 * 3 * 2 = 18,其他模型来自max(n.trees),所以不需要54整数。)