我正在尝试使用代码在插入符号中完全可重现的并行模型,但不了解如何设置种子对象中的向量的大小.对于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)
我将分两部分提出你的问题:
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)
在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计算出来,而不是我们稍后会看到的.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基于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"))
}
}
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)
现在,让我们通过你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
>
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整数).