R:来自runif和Mersenne Twister种子的随机值的极端聚束

R:来自runif和Mersenne Twister种子的随机值的极端聚束,r,random,mersenne-twister,R,Random,Mersenne Twister,当使用R并使用set.seed和kind=NULL选项设置种子时,我们的代码中面临着一种奇怪的情况(除非我弄错了,否则它会解决kind=“default”;默认值是“Mersenne Twister”) 在调用runif之前,我们使用上游系统生成的(8位)唯一ID设置种子: seeds = c( "86548915", "86551615", "86566163", "86577411", "86584144", "86584272", "86620568", "86724613",

当使用R并使用
set.seed
kind=NULL
选项设置种子时,我们的代码中面临着一种奇怪的情况(除非我弄错了,否则它会解决
kind=“default”
;默认值是
“Mersenne Twister”

在调用
runif
之前,我们使用上游系统生成的(8位)唯一ID设置种子:

seeds = c(
  "86548915", "86551615", "86566163", "86577411", "86584144", 
  "86584272", "86620568", "86724613", "86756002", "86768593", "86772411", 
  "86781516", "86794389", "86805854", "86814600", "86835092", "86874179", 
  "86876466", "86901193", "86987847", "86988080")

random_values = sapply(seeds, function(x) {
  set.seed(x)
  y = runif(1, 17, 26)
  return(y)
})
这将给出聚集在一起的非常的值

> summary(random_values)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  25.13   25.36   25.66   25.58   25.83   25.94 
当我们使用
kind=“Knuth-TAOCP-2002”
时,
runif
的这种行为消失了,我们得到的值似乎分布得更均匀

random_values = sapply(seeds, function(x) {
  set.seed(x, kind = "Knuth-TAOCP-2002")
  y = runif(1, 17, 26)
  return(y)
})
省略输出


这里最有趣的事情是,这不会发生在Windows上——只会发生在Ubuntu上(下面是Ubuntu和Windows的输出)

Windows输出: 有人能帮助理解发生了什么吗

Ubuntu 窗户
当您将Mersenne Twister与单个种子一起使用时,可以合理地假设生成的值近似独立且分布相同。不幸的是,对于从不同种子开始的两个流生成的值没有任何保证。例如,请参见

在您的情况下,我建议您要么使用SC线程中建议的一种种子选择策略,要么切换到对并行流有更好保证的PRNG。一个选项是L'Ecuyer的“RngStreams”生成器:

set.seed(0, kind = "L'Ecuyer-CMRG")
即使有了这个PRNG,我也不知道它是否仍然适用于使用任意种子对PRNG进行播种,并获得大致独立的流


就Ubuntu和Windows之间的差异而言,这些系统中的一个可能使用32位生成器,另一个使用64位生成器。

注意:这个答案总结了R-devel邮件列表中关于这个问题的讨论内容。我只是试图捕捉和总结那里最初阐述的想法

尽管您保证这些数字不是一个特殊构造的边缘案例,但它们看起来就是这样。以下是检查生成值分布的原始序列加代码:

seeds = c(
    86548915, 86551615, 86566163, 86577411, 86584144, 86584272,
    86620568, 86724613, 86756002, 86768593, 86772411, 86781516,
    86794389, 86805854, 86814600, 86835092, 86874179, 86876466,
    86901193, 86987847, 86988080)
checkit <- function(seeds) {
    sapply(seeds, function(x) {
        set.seed(x)
        y = runif(1, 17, 26)
        return(y)
    })}
原始序列似乎有一些特殊之处,因为对其进行最小的修改不会产生相同的令人惊讶的结果:

summary(checkit(seeds+1))
## Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 17.18   19.65   22.75   22.02   24.37   25.79

summary(checkit(seeds-1))
## Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##17.15   18.44   19.92   20.77   22.97   25.95 
在原始序列所跨越的范围内的所有种子中,预期数量产生的值在观察范围内:

possible.seeds <- min(seeds):max(seeds)

s25 <- Filter(function(s){
    set.seed(s)
    x <- runif(1,17,26)
    x > 25.12 & x < 25.95},
    possible.seeds)

length(s25)/length(possible.seeds)
##[1] 0.09175801

所有这些都表明,原始序列可能实际上是(可能是无意中)特殊构造的边缘情况。

作为序列是边缘情况的进一步证据,您可以关注构造的假定随机值的范围。17号和26号有点让人分心。在0和1上使用uniform重复您的实验会产生同样不可能的结果:

f <- function(x) {
  set.seed(x)
  runif(1)
}

 check_range <-function(seeds){
   vals <- sapply(seeds,f)
   max(vals)-min(vals)
}
当在21个随机种子上运行时,
检查范围(种子)
的合理模型是,它是从
U(0,1)
中抽取的大小为21的随机样本的样本范围。其详细信息如下所示:

f <- function(x){420*x^19*(1-x)}
f积分(f,0,0.09)
2.334272e-20,绝对误差<2.6e-34
为了检查在这样播种Mersenne捻线机时对样本范围进行建模是否合理,您可以进行以下实验:

ranges <- replicate(1000,check_range(sample(8548915:86988080,21)))
x <- seq(0,1,0.01)
y <- f(x)
hist(ranges,freq = FALSE,xlim =c(0,1))
points(x,y,type = "l")
abline(v=0.09)

确定生成种子的“上游过程”的范围。这似乎是您提供的特定种子集的人工制品,对于大小类似的随机种子集通常不正确如果我在Windows上运行您的代码,我会得到相同的结果。我在Windows10上使用了
3.4.1
。平台之间的随机数生成通常没有区别。除非我完全误解了你说“这不会发生”的意思@dww当然,我们也在其他8位数字上测试了它们&我们无法复制。然而,这些是由非对抗性系统生成的诚实的数字,该系统不知道这些数字除了用于实体的唯一键之外,还用于其他任何用途——这些不是特殊构造的边缘情况。很高兴知道哪些种子会起作用,哪些种子不会起作用,以及为什么。@MrFlick我可以在运行R3.3.2的Windows 10计算机上为您提供
sessionInfo
,其中的随机数似乎不是随机分布的,就像在这个问题中一样。而且,奇怪的是,这被否决了。
possible.seeds <- min(seeds):max(seeds)

s25 <- Filter(function(s){
    set.seed(s)
    x <- runif(1,17,26)
    x > 25.12 & x < 25.95},
    possible.seeds)

length(s25)/length(possible.seeds)
##[1] 0.09175801
table(seeds %in% s25)

##TRUE 
##  21 
f <- function(x) {
  set.seed(x)
  runif(1)
}

 check_range <-function(seeds){
   vals <- sapply(seeds,f)
   max(vals)-min(vals)
}
> check_range(seeds)
[1] 0.09026112
f <- function(x){420*x^19*(1-x)}
> integrate(f,0,0.09)
2.334272e-20 with absolute error < 2.6e-34
ranges <- replicate(1000,check_range(sample(8548915:86988080,21)))
x <- seq(0,1,0.01)
y <- f(x)
hist(ranges,freq = FALSE,xlim =c(0,1))
points(x,y,type = "l")
abline(v=0.09)