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

Tom*_*Tom 2 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
Run Code Online (Sandbox Code Playgroud)

how*_*waj 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)
Run Code Online (Sandbox Code Playgroud)

11seeds <- vector(mode = "list", length = 11)(n_repeats*nresampling)+1,所以你的情况,你使用10-fold CV,所以10+1 = 11.如果您正在使用repeatedcvnumber=10 and repeats = 5您将要替换的11通过(5*10)+1 = 51.

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

54sample.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计算出来,而不是我们稍后会看到的.seedsinteraction.depth * shrinkage * n.minobsinnode3 * 3 * 2 = 183*3*3*2 = 54

但是,如果您使用的是SVM具有网格的模型,那么svmGrid <- expand.grid(sigma= 2^c(-25, -20, -15,-10, -5, 0), C= 2^c(0:5))您的价值就是6 * 6 = 36

请记住,使用的目标seeds是允许reproducible research通过为每个重采样迭代设置适合的模型的种子.

所述seeds[[11]]<-sample.int(1000, 1)用于设置的最后(最佳)模型拟合到完整的数据集种子.

2 - 如果指定值<18,为什么会出现错误,但值> = 18时没有错误

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

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
Run Code Online (Sandbox Code Playgroud)

因此,通过检查train.default我能够找到它的来源.错误消息由stopin行7 to 10基于badSeed4和中的测试触发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"))
        }
    }
Run Code Online (Sandbox Code Playgroud)

这个数字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'")
    }
Run Code Online (Sandbox Code Playgroud)

现在,我们需要找到对象models.它被赋予第models <- getModelInfo(method, regex = FALSE)[[1]]2行的值:

    else {
2       models <- getModelInfo(method, regex = FALSE)[[1]]
        if (length(models) == 0) 
            stop(paste("Model", method, "is not in caret's built-in library"))
    }
Run Code Online (Sandbox Code Playgroud)

由于我们正在使用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)
}
> 
Run Code Online (Sandbox Code Playgroud)

loop(在上面第3行)的值指定为:

loop <- ddply(grid, c("shrinkage", "interaction.depth", "n.minobsinnode"),
                              function(x) c(n.trees = max(x$n.trees)))`
Run Code Online (Sandbox Code Playgroud)

现在,让我们通过你grid54 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
> 
Run Code Online (Sandbox Code Playgroud)

啊!我们找到了.值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)))
Run Code Online (Sandbox Code Playgroud)

测试的第一部分(length(trControl$seeds) < length(trControl$index) + 1)FALSE,但第二部分(any(numSeeds[-length(numSeeds)] < nrow(trainInfo$loop)))TRUE针对所有valuse少于18[来自nrow(trainInfo$loop)],并且FALSE所有valuse都大于18.这就是错误被触发的原因<18而不是>=18.正如我上面所说,插入符号seeds基于interaction.depth * shrinkage * n.minobsinnode你的情况计算3 * 3 * 2 = 18(模型适合于max(n.trees),其他模型是从它派生的,因此不需要54整数).