我正在尝试将代码用于插入符号中完全可重现的并行模型,但不了解如何设置种子对象中向量的大小。对于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
答案 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 CV
,10+1 = 11
。如果您将repeatedcv
与number=10 and repeats = 5
一起使用,则会将11
替换为(5*10)+1 = 51
。
10
中的for(i in 1:10)
为(n_repeats*nresampling)
。在您的情况下,它是10
,因为您正在使用10-fold CV
。同样,如果您将repeatedcv
与number=10 and repeats = 5
一起使用,则会for(i in 1:50)
。
54
中的sample.int(n=1000, 54)
是number of tuning parameter combinations
。在您的情况下,4 parameters
为3,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.default
和stop
中的测试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
整数。)