如何让R的lapply(和mclapply)恢复随机数生成器的状态?

12

R在lapply内部忽略设置.Random.seed。但是,使用set.seed却可以正常工作。

一些代码:

# I can save the state of the RNG for a few seeds
seed.list <- lapply( 1:5, function(x) {
                        set.seed(x)
                        seed.state <- .Random.seed
                        print( rnorm(1) )
                        return( seed.state )}) 
#[1] -0.6264538
#[1] -0.8969145
#[1] -0.9619334

# But I get different numbers if I try to restore 
# the state of the RNG inside of an lapply
tmp.rest.state <-  lapply(1:5, function(x) { 
                        .Random.seed <- seed.list[[x]]
                        print(rnorm(1))})
# [1] -0.2925257
# [1] 0.2587882
# [1] -1.152132

# lapply is just ignoring the assignment of .Random.seed
.Random.seed <- seed.list[[3]]
print( rnorm(1) ) # The last printed value from seed.list
# [1] -0.9619334
print( rnorm(1) ) # The first value in tmp.rest.state
# [1] -0.2925257
我的目标是对MCMC运行进行检查点以便可以精确地恢复它们。我可以轻松保存RNG的状态,只是我不能让R在lapply循环内加载它!是否有一种方法强制R注意设置.Random.seed?或者还有更简单的方法吗? 如果有影响的话,我正在使用64位的R:
R version 2.15.1 (2012-06-22) -- "Roasted Marshmallows"
Platform: x86_64-pc-linux-gnu (64-bit)

在Ubuntu 12.04 LTS下:

nathanvan@nathanvan-N61Jq:~$ uname -a
Linux nathanvan-N61Jq 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
1个回答

10

这是因为在调用lapply时,.Random.seed被评估为局部对象。

你需要在全局环境中分配.Random.seed的值:

tmp.rest.state <- lapply(seed.list, function(x) {
    assign(".Random.seed", x, envir=globalenv())
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555
你的代码不起作用的原因是 .Random.seed被分配在lapply中的匿名函数环境中,但rnorm()在全局环境中查找.Random.seed
为了记录,以下是我的第一次尝试,它只能在某些情况下工作:
这是一种修复它的方式,通过使用<<-。(是的,我知道这被 frowned upon,但可能是有道理的。另一种选择是使用eval()并强制在调用环境中进行评估。
tmp.rest.state <- lapply(seed.list, function(x) {
    .Random.seed <<- x
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555

请注意,如果您的lapply()嵌套在另一个函数中,则此解决方案将无法使用,因为<<-仅在父环境中进行评估,而不是全局环境。


1
也许将.Random.seed放在一个命名环境中会增加通用性?或者使用引用类的解决方案? - IRTFM
4
也可以使用.GlobalEnv$.Random.seed <- x.GlobalEnv[[".Random.seed"]] <- x。这两种方法可以设置随机数发生器的种子值,以便生成可重复的随机数序列。请注意,这些代码应该在R语言环境中运行。 - Josh O'Brien
请注意,如果您的lapply()嵌套在另一个函数中,则此解决方案将无法正常工作,因为<<-仅在父环境中进行评估,而不是全局环境。这并不完全正确。<<-首先会在父环境中查找是否存在具有正确名称的对象,然后转到祖父环境,依此类推。如果没有找到变量,则在全局环境中进行赋值。 - Emil Bode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接