【问题标题】:set.seed() in a local environmentset.seed() 在本地环境中
【发布时间】:2013-04-24 13:36:45
【问题描述】:

是否可以在不影响后续随机数生成的本地环境中使用set.seed()?在某些函数中设置种子以获得可重复的结果是很常见的,但我认为这很不幸,因为它甚至会在环境之外影响后续几代随机数。

有没有可能避免这种行为?

set.seed(123)
runif(1) #[1] 0.2875775
runif(1) #[1] 0.7883051
local({
  set.seed(123)
  print(runif(1))
})
#[1] 0.2875775
runif(1) #[1] 0.7883051 (This should not be the second number again)

【问题讨论】:

标签: r random


【解决方案1】:

来自?set.seed

[如果]没有种子;当需要一个时,从当前时间(从 R 2.14.0 开始,进程 ID)创建一个新的。

set.seed(42)
rnorm(1)
#[1] 1.370958
rm(.Random.seed)
rnorm(1)
#[1] -0.4352643
set.seed(42)
rnorm(1)
#[1] 1.370958
rm(.Random.seed)
rnorm(1)
#[1] -2.338973

【讨论】:

  • 这并没有多大帮助,因为通常的做法是在模拟(或其他)一开始就设置种子以获得可重复的结果。但可能你有多次运行一种方法,这些方法应该是随机的。现在这个方法调用了一个函数,该函数调用了set.seed()。现在,每次运行中的以下随机数都是相同的,这不是我想要的。 rm(.Random.seed) 也会导致不可重现的结果。
  • 我不明白。要么你想要可重现,那么你需要使用set.seed,或者你想要完全随机,那么你需要一个随机种子。也许你想要for (i in 1:10) {set.seed(i); rnorm(1)}之类的东西?
  • @jakobr 如果您正在执行多次运行,您可以在一个进程中将它们序列化,这样您就可以按照 Roland 的建议进行操作并一个接一个地设置新种子,或者您将使用并行计算,其中如果您可以查看doRNG 包和%dorng% 循环。
【解决方案2】:

您可以在函数开始时设置种子,然后在退出时恢复旧种子。这是一个快速演示,在函数之后进行测试。

rnorm_seed <- function(n, mean = 0, sd = 1, seed = NULL) {

  if (!is.null(seed)) {
    # reinstate system seed after simulation
    sysSeed <- .GlobalEnv$.Random.seed
    on.exit({
      if (!is.null(sysSeed)) {
        .GlobalEnv$.Random.seed <- sysSeed 
      } else {
        rm(".Random.seed", envir = .GlobalEnv)
      }
    })
    set.seed(seed, kind = "Mersenne-Twister", normal.kind = "Inversion")
  }
  
  rnorm(n, mean, sd)
}

# test
set.seed(8675309)
rnorm(1) # -0.9965824
rnorm(1) #  0.7218241
rnorm(1) # -0.6172088

set.seed(8675309)
rnorm(1) # -0.9965824
rnorm(1) #  0.7218241
rnorm_seed(1, seed = 8675309) # -0.9965824
rnorm(1) # -0.6172088

【讨论】:

    猜你喜欢
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 2017-11-12
    • 2022-01-23
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多