Seed和clusterApply-如何选择特定的运行?

Ann*_*etz 5 parallel-processing r k-means

我正在大型数据集(636,688行x 7列)上执行k-均值,因此转向并行化。我的结果需要可重现。我可以用做clusterSetRNGStreamparallel包。这是一个使用库中Boston数据集的示例MASS

library(parallel)
cl <- makeCluster(detectCores())
clusterSetRNGStream(cl, iseed = 1234)
clusterEvalQ(cl, library(MASS))
results <- clusterApply(cl, rep(25, 4), function(nstart) kmeans(Boston, 4, nstart = nstart))
check.results <- sapply(results, function(result) result$size)
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)

check.results列表示对于k-means算法的给定遍历,每个相应群集的观察次数。check.results然后,我的样子如下:

     [,1] [,2] [,3] [,4]
[1,]   38  268  102  102
[2,]  268   98   98   38
[3,]   98  102   38  268
[4,]  102   38  268   98
Run Code Online (Sandbox Code Playgroud)

如果将results变量更改为include rep(25, 2)而不是rep(25, 4),则会得到:

     [,1] [,2]
[1,]   38  268
[2,]  268   98
[3,]   98  102
[4,]  102   38
Run Code Online (Sandbox Code Playgroud)

完美-无论我运行4次迭代还是仅进行2次迭代,前2次运行的大小都保持不变。如果继续更改迭代次数,您将看到每个单独的运行都保持不变。

我的问题-如何在不进行前三轮跑的情况下特别选择第四轮跑?是否在下面的基础 iseed 保存了特定的种子clusterSetRNGStream

Ste*_*ton 7

clusterSetRNGStream函数不能很好地支持您想要的那种可重复性。问题在于,它只是初始化每个集群工作人员以从不同的随机数流中抽取随机数,当对给定数量的工作人员使用 clusterApply 时,这是可重现的。但是要执行特定任务,您必须在正确的工作线程上执行它才能获得正确的流,并在该流中快进,即使您知道每个任务消耗的随机数的确切数量,也不支持此操作任务。

相反,我建议您使用较低级别的函数为每个任务分配不同的随机数子流。您可以通过使用以下函数生成任务种子来做到这一点nextRNGSubStream

library(parallel)
# This is based on the clusterSetRNGStream function from
# the parallel package, copyrighted by The R Core Team
getseeds <- function(ntasks, iseed) {
  RNGkind("L'Ecuyer-CMRG")
  set.seed(iseed)
  seeds <- vector("list", ntasks)
  seeds[[1]] <- .Random.seed
  for (i in seq_len(ntasks - 1)) {
    seeds[[i + 1]] <- nextRNGSubStream(seeds[[i]])
  }
  seeds
}
Run Code Online (Sandbox Code Playgroud)

由于我们没有使用clusterSetRNGStream,因此在初始化工作人员时,您需要将随机数生成器设置为“L'Ecuyer-CMRG”:

cl <- makeCluster(detectCores())
clusterEvalQ(cl, { library(MASS); RNGkind("L'Ecuyer-CMRG") })
Run Code Online (Sandbox Code Playgroud)

关键是从工作函数中设置“.Random.seed”的值,以便为每个任务使用正确的随机数子流:

worker <- function(nstart, seed, centers=4) {
  assign(".Random.seed", seed, envir=.GlobalEnv)
  kmeans(Boston, centers, nstart = nstart)
}
Run Code Online (Sandbox Code Playgroud)

由于我们正在迭代nstartseed值,因此您可以使用clusterMap而不是clusterApply执行任务:

n <- 4
nstarts <- rep(25, n)
seeds <- getseeds(n, 1234)
results <- clusterMap(cl, worker, nstarts, seeds)
Run Code Online (Sandbox Code Playgroud)

要重现第四个任务的结果,请指定第四个种子:

itasks <- c(4)
results <- clusterMap(cl, worker, nstarts[itasks], seeds[itasks])
Run Code Online (Sandbox Code Playgroud)

使用此方法,即使通过clusterMap .scheduling="dynamic"参数进行负载平衡,您也可以获得可重现的结果,因为结果并不依赖于执行任务的工作线程,就像使用clusterSetRNGStream.


请注意,您可以使用参数来指定函数参数的clusterMap MoreArgs值:centersworker

results <- clusterMap(cl, worker, nstarts, seeds, MoreArgs=list(centers=5))
Run Code Online (Sandbox Code Playgroud)