R中重复随机数,如何停止?

问题描述 投票:0回答:2

我正在 R 中生成一小部分随机均匀数字(在本例中为 10,000 个),并且我发现重复率惊人(例如,在 10,000 个数字抽取中每隔几次重复就会出现一次)。为什么会发生这种情况,我怎样才能(有效地)阻止它?

这是一个最小的工作示例,我只是继续绘制 100 万个 unif(0,1) 值。这似乎会产生许多重复的值。我在查找重复项方面确实遇到了一些问题,因此不得不在下面做一些难看的事情,并且有时由于舍入或其他原因,这可能无法找到重复项,但它似乎在我的机器上工作。

rs_val <- .Random.seed 
tvals <- runif(10^6,0,1) 
tr1 <- as.numeric(names(which(table(tvals)>1)))[1] 
tr_idx <- which(abs(tvals-tr1)<0.000000001) 
tr_idx[1]
tr_idx[2]
format(tvals[tr_idx[1]],digits=22) 
format(tvals[tr_idx[2]],digits=22) 
tvals[tvals==as.numeric(format(tvals[tr_idx[1]],digits=22))]

想必,对于现代伪随机数生成器来说,100 万次抽奖根本不应该那么多,是吗?我在这里看到了一些关于 C++ 的类似问题的帖子,但没有关于 R 的帖子。在后者中,它与随机抽取发生得比随机种子重置或类似问题更快有关。

有人可以对上述代码进行有效的修改以防止重复的随机数问题吗?基本上,我只是在很长的时间线上模拟泊松过程,这会导致同时发生的事件,这是有问题的。我想,我可以只进行模拟并放弃重复的抽奖,但最好不必这样做。

r random
2个回答
3
投票

来自

?Random

不要依赖 RNG 低阶位的随机性。大部分的 提供的统一生成器返回 32 位整数值,这些值是 转换为双精度数,因此它们最多采用 2^32 个不同的值,并且 长时间运行将返回重复值(Wichmann-Hill 是 例外,并且都给出至少 30 个不同的位。)

这很容易验证:

identical(min(diff(unique(sort(runif(1e6))))), 2^-32)
#> [1] TRUE
sum((runif(1e6) %% 2^-32))
#> [1] 0

因此,除了使用 Wichmann-Hill 之外,另一个选择是对

1:(2^32 - 1)
进行采样而不进行替换,然后除以
2^32
,尽管这不如使用 Wichmann-Hill 的
runif
那样高效。

system.time(x <- sample(2^32 - 1, 1e6)/2^32)
#>    user  system elapsed 
#>    0.16    0.01    0.17
RNGkind(kind="Wichmann-Hill")
system.time(x <- runif(1e6))
#>    user  system elapsed 
#>    0.04    0.00    0.05

第二个选项是调用

runif
两次:一次用于 32 位精度,然后第二次调用以填充间隙以使其成为双精度:

RNGkind(kind="default")

runif64 <- function(n) runif(n) + runif(n, -2^-33, 2^-33)
x <- runif64(1e6)
range(x)
#> [1] 4.710828e-07 9.999975e-01
anyDuplicated(x)
#> [1] 0

runif64
的速度大约是调用
runif
的两倍。

microbenchmark::microbenchmark(
  runif64(1e6),
  runif(1e6)
)
#> Unit: milliseconds
#>            expr     min       lq     mean median       uq      max neval
#>  runif64(1e+06) 61.1622 63.33880 65.91086 64.926 67.18855 109.3689   100
#>    runif(1e+06) 29.7481 30.34125 31.91007 30.997 33.71515  40.3735   100

1e6
个可能值的样本中看到任何重复值的概率非常小:
2^64



3
投票
https://stats.stackexchange.com/questions/465536/r-problem-with-runif- generated-number-repeats-more-often-than-expected-after

将 RNGkind 设置为“Wichmann-Hill”,而 R 中的默认值是“Mersenne-Twister”。我确信每种特定方法都有优点和缺点,但我只需要确保没有重复并且相当统一。

library(Rmpfr) n <- mpfr(2^64, 128) m <- mpfr(1e6, 128) as.numeric(1 - exp(lgamma(n + 1) - m*log(n) - lgamma(n - m + 1))) #> [1] 2.710503e-08

请注意,“Wichmann-Hill”类型显然是“可预测的”(如链接帖子中所述)。我认为这对于我的特定应用程序来说不是问题,因为我只需要大致随机均匀的绘制而不重复。

© www.soinside.com 2019 - 2024. All rights reserved.