1

我最近一直在研究 R 包caret,并且有一个关于训练期间模型的可重复性和比较的问题,我还不能完全确定。

我的意图是,每个train调用以及每个生成的模型都使用相同的交叉验证拆分,以便交叉验证的初始存储结果与构建期间计算的模型的样本外估计具有可比性。

我见过的一种方法是您可以在每次train调用之前指定种子,如下所示:

set.seed(1)
model <- train(..., trControl = trainControl(...))
set.seed(1)
model2 <- train(..., trControl = trainControl(...))
set.seed(1)
model3 <- train(..., trControl = trainControl(...))

但是,trainControl在调用之间共享一个对象是否train意味着它们通常使用相同的重采样和索引,或者我是否必须将seeds参数显式传递给函数。列车控制对象在使用时是否具有随机功能或是否在声明时设置?

我目前的方法是:

set.seed(1)
train_control <- trainControl(method="cv", ...)
model1 <- train(..., trControl = train_control)
model2 <- train(..., trControl = train_control)
model3 <- train(..., trControl = train_control)

这些火车呼叫是否将使用相同的拆分并具有可比性,还是我必须采取进一步措施来确保这一点?即在trainControl制作对象时指定种子,或在每列火车前调用set.seed?或两者?

希望这是有道理的,而不是完全的垃圾。任何帮助


我正在查询的代码项目可以在这里找到。它可能更容易阅读,你会明白的。

4

1 回答 1

0

trainControl除非使用index我推荐的参数明确说明,否则在定义期间不会创建 CV 折叠。这些可以使用以下专用caret功能之一创建:

createFolds
createMultiFolds
createTimeSlices
groupKFold

也就是说,在trainControl定义之前使用特定的种子不会导致相同的 CV 折叠。

例子:

library(caret)
library(tidyverse)

set.seed(1)
trControl = trainControl(method = "cv",
                         returnResamp = "final",
                         savePredictions = "final")

创建两个模型:

knnFit1 <- train(iris[,1:4], iris[,5],
                 method = "knn",
                 preProcess = c("center", "scale"),
                 tuneLength = 10,
                 trControl = trControl)

ldaFit2 <- train(iris[,1:4], iris[,5],
                 method = "lda",
                 tuneLength = 10,
                 trControl = trControl)

检查相同的索引是否在相同的折叠中:

knnFit1$pred %>%
  left_join(ldaFit2$pred, by = "rowIndex") %>%
  mutate(same = Resample.x == Resample.y) %>%
  {all(.$same)}
#FALSE

如果您在每次train调用之前设置相同的种子

set.seed(1)
knnFit1 <- train(iris[,1:4], iris[,5],
                 method = "knn",
                 preProcess = c("center", "scale"),
                 tuneLength = 10,
                 trControl = trControl)

set.seed(1)
ldaFit2 <- train(iris[,1:4], iris[,5],
                 method = "lda",
                 tuneLength = 10,
                 trControl = trControl)


set.seed(1)
rangerFit3 <- train(iris[,1:4], iris[,5],
                 method = "ranger",
                 tuneLength = 10,
                 trControl = trControl)


knnFit1$pred %>%
  left_join(ldaFit2$pred, by = "rowIndex") %>%
  mutate(same = Resample.x == Resample.y) %>%
  {all(.$same)}

knnFit1$pred %>%
  left_join(rangerFit3$pred, by = "rowIndex") %>%
  mutate(same = Resample.x == Resample.y) %>%
  {all(.$same)}

折叠中将使用相同的索引。但是,在使用并行计算时,我不会依赖这种方法。因此,为了确保使用相同的数据拆分,最好使用index/indexOut参数手动定义它们trainControl

当您手动设置索引参数时,折叠将是相同的,但这并不能确保由相同方法制作的模型将相同,因为大多数方法都包含某种随机过程。因此,为了完全可重复,建议在每次火车调用之前设置种子。当并行运行以获得完全可重现的模型时,需要设置seeds参数。trainControl

于 2018-10-03T09:12:02.590 回答