我无法设置种子值来从parallelSVM()获得可重复的结果。

 library(e1071)
 library(parallelSVM)

 data(iris)
 x <- subset(iris, select = -Species)
 y <- iris$Species

set.seed(1)
model       <- parallelSVM(x, y)
parallelPredictions <- predict(model, x)

set.seed(1)
model2       <- parallelSVM(x, y)
parallelPredictions2 <- predict(model2, x)

all.equal(parallelPredictions,parallelPredictions2)



我知道这不是为多核操作设置种子值的正确方法,但是我不知道该怎么做。

我知道在使用mclapply时有一个选项,但这对我的情况没有帮助。



编辑:我找到了一种解决方案,方法是使用trainSample()循环更改parallelSVM中的函数tracedoRNG包中的foreach包。

有人知道更好的解决方案吗?

最佳答案

简而言之,parallelSVM中没有实现的方法可以解决此问题。但是,该软件包使用foreachdoParallel软件包来处理其并行操作。并在stackoverflow上足够努力地挖掘一个解决方案是可能的!

归功于this answer(使用doRNG软件包)和this answer,以便为我提供一个更简单的封闭式解决方案的想法。

解:

parallelSVM包中,并行化是通过parallelSVM::registerCores函数进行的。此函数仅使用内核数调用doParallel::registerDoParallel,并且不再使用其他参数。我的想法只是更改parallelSVM::registerCores函数,以使其在创建新集群后自动将种子设置为。

在执行并行计算(其中需要并行种子)时,需要确保两件事


需要将种子提供给集群中的每个节点
生成器必须是跨群集渐近随机的生成器。


幸运的是,doRNG包可以处理第一个包,并使用可以在2上正常运行的种子。使用unlockNamespaceassign的组合,我们可以覆盖parallelSVM::registerCores,从而包括对doRNG::registerDoRNG的调用。适当的种子(答案结尾处的功能)。这样做,实际上可以得到如下所示的适当重现性:

library(parallelSVM)
library(e1071)
data(magicData)
set.seed.parallelSWM(1) #<=== set seed as we would normally.
#Example from help(parallelSVM)
system.time(parallelSvm1 <- parallelSVM(V11 ~ ., data = trainData[,-1],
                                       numberCores = 4, samplingSize = 0.2,
                                       probability = TRUE, gamma=0.1, cost = 10))
system.time(parallelSvm2 <- parallelSVM(V11 ~ ., data = trainData[,-1],
                                       numberCores = 4, samplingSize = 0.2,
                                       probability = TRUE, gamma=0.1, cost = 10))
pred1 <- predict(parallelSvm1)
pred2 <- predict(parallelSvm2)
all.equal(pred1, pred2)
[1] TRUE
identical(parallelSvm1, parallelSvm2)
[1] FALSE


请注意,identical无权正确评估parallel::parallelSvm输出的对象,因此最好进行预测以检查模型是否相同。

为了安全起见,请检查问题中可复制示例是否也是如此

x <- subset(iris, select = -Species)
y <- iris$Species
set.seed.parallelSWM(1) #<=== set seed as we would normally (not necessary if above example has been run).
model       <- parallelSVM(x, y)
model2       <- parallelSVM(x, y)
parallelPredicitions <- predict(model, x)
parallelPredicitions2 <- predict(model2, x)
all.equal(parallelPredicitions, parallelPredicitions2)
[1] TRUE


ew

最后,如果完成,或者再次需要随机种子,则可以通过执行以下操作重置种子

set.seed.parallelSWM() #<=== set seed to random each execution (standard).
#check:
model       <- parallelSVM(x, y)
model2       <- parallelSVM(x, y)
parallelPredicitions <- predict(model, x)
parallelPredicitions2 <- predict(model2, x)
all.equal(parallelPredicitions, parallelPredicitions2)
[1] "3 string mismatches"


(由于未设置RNNG种子,输出将有所不同)

set.seed.parallelSWM函数

归功于this answer。请注意,我们可能不必加倍分配,但是在这里我只是复制了答案,而没有检查代码是否可以进一步减少。

set.seed.parallelSWM <- function(seed, once = TRUE){
    if(missing(seed) || is.character(seed)){
        out <- function (numberCores)
        {
            cluster <- parallel::makeCluster(numberCores)
            doParallel::registerDoParallel(cluster)
        }
    }else{
        require("doRNG", quietly = TRUE, character.only = TRUE)
        out <- function(numberCores){
            cluster <- parallel::makeCluster(numberCores)
            doParallel::registerDoParallel(cluster)
            doRNG::registerDoRNG(seed = seed, once = once)
        }
    }
    unlockBinding("registerCores", as.environment("package:parallelSVM"))
    assign("registerCores", out, "package:parallelSVM")
    lockBinding("registerCores", as.environment("package:parallelSVM"))
    unlockBinding("registerCores", getNamespace("parallelSVM"))
    assign("registerCores", out, getNamespace("parallelSVM"))
    lockBinding("registerCores", getNamespace("parallelSVM"))
    #unlockBinding("registerCores", as.environment("package:parallelSVM"))
    invisible()
}

08-20 02:02