有没有办法用Python生成不相关的随机变量?

时间:2016-12-31 13:31:00

标签: python python-3.x random

假设我想生成两个随机变量XY,它们在[0,1]中不相关且均匀分布。

生成这样的非常天真的代码如下,它将random函数调用两次:

import random 
xT=0 
yT=0 
xyT=0 
for i in range(20000):
    x = random.random()
    y = random.random()
    xT += x
    yT += y
    xyT += x*y

xyT/20000-xT/20000*yT/20000

然而,随机数实际上是由公式生成的伪随机数,因此它们是相关的。

如何生成两个不相关的(或尽可能少的相关)随机变量?

2 个答案:

答案 0 :(得分:7)

关于RNG的数学是可靠的。现在最流行的实现也是如此。因此,您的猜想

  

由公式生成,因此它们是相关的。

不正确。

但如果你真的非常深思这么想,那就有了:hardware random number generatorsrandom.org的网站长期以来一直在提供硬件RNG“即服务”。这是一个例子(在R中,我使用了更多,但有is an official Python client):

R> library(random)
R> randomNumbers(min=1, max=20000)    # your range, default number
         V1    V2    V3    V4    V5
 [1,]   532 19452  5203 13646  5462
 [2,]  4611 10814  3694 12731   566
 [3,] 11884 19897  1601 10652   791
 [4,] 17427  9524  7522  1051  9432
 [5,]  5426  5079  2232  2517  4883
 [6,] 13807  9194 19980  1706  9205
 [7,] 13043 16250 12827  2161 10789
 [8,]  7060  6008  9110  8388  1102
 [9,] 12042 19342  2001 17780  3100
[10,] 11690  4986  4389 14187 17191
[11,] 19574 13615  3129 17176  5590
[12,] 11104  5361  8000  5260   343
[13,]  7518  7484  7359 16840 12213
[14,] 14914  1991 19952 10127 14981
[15,] 13528 18602 10182  1075 16480
[16,]  9631 17160 19808 11662 10514
[17,]  4827 13960 17003   864 11159
[18,]  8939  7095 16102 19836 15490
[19,]  8321  6007  1787  6113 17948
[20,]  9751  7060  8355 19065 15180
R> 

编辑: OP似乎不相信,所以有一个快速可重现的模拟(再次,在R中,因为这是我使用的):

R> set.seed(42)               # set seed for RNG
R> mean(replicate(10, cor(runif(100), runif(100))))
[1] -0.0358398
R> mean(replicate(100, cor(runif(100), runif(100))))
[1] 0.0191165
R> mean(replicate(1000, cor(runif(100), runif(100))))
[1] -0.00117392
R> 

所以你看到,当我们从10到100再到1000次重复只有100 U(0,1)时,相关性估计变为零。

我们可以通过绘图,恢复相同的数据以及更多内容来使这一点变得更好:

R> set.seed(42)
R> x <- 10^(1:5)   # powers of ten from 1 to 5, driving 10^1 to 10^5 sims
R> y <- sapply(x, function(n) mean(replicate(n, cor(runif(100), runif(100)))))
R> y    # same first numbers as seed reset to same start
[1] -0.035839756  0.019116460 -0.001173916 -0.000588006 -0.000290494
R> plot(x, y, type='b', main="Illustration of convergence towards zero", log="x")
R> abline(h=0, col="grey", lty="dotted")

enter image description here

答案 1 :(得分:3)

简答:在随机种子上使用Bays-Durham shuffle。

更长的回答:

我确定你知道计算机算法给出的伪随机数不是真正随机的 - 它们只是为了通过大多数随机化测试,因此足够好&#34;对于大多数用途。对于不相关的随机变量也是如此:你永远不会得到真正不相关的随机变量,但你的目标应该是让它们通过尽可能多的相关性测试,并且足够好&#34;为了你的目的。

标准线性同余调制器失败相关性测试的主要方式是当您查看由数字生成的2空间的小区域时。成对的数字在绘制时显示出明显的线条,因此不是真正不相关的。这仅在您查看所有生成的数字对的非常小的区域时才重要。这是你需要做的吗?请注意,Python的random()函数使用&#34; Mersenne Twister&#34;而不是线性同余调制器,因此不太可能失败这样的测试。请参阅Wikipedia's list of the disadvantages of the Mersenne Twister,了解Python的随机数生成器是否适合您的目的。请注意,Python的实现详细显示了later in the page

我在Borland Delphi(Object Pascal和x86汇编程序)中编写例程以避免相关性。我已经切换到Python但尚未重写这些例程。 Bays-Durham shuffle的想法是使用内置的随机数生成器为您提供一个随机整数(用于生成0到1之间的浮点数的整数)。然后使用该整数指向先前生成的随机整数数组。您可以选择指向的整数,并使用新生成的整数将其替换为数组。返回以前在数组中的整数,如果需要将其转换为0到1之间的数字。

我使用32个整数数组实现了这个并测试了这个新的生成器。这现在通过了Delphi的随机数发生器失败的相关性测试。我再说一遍,这不会通过所有相关性测试,但它确实传递的不仅仅是标准的生成器,而且它对我的使用来说绝对够用。

如果您需要查看Python的实现,请询问并且我将尝试花时间编写一个。在那之前,查看&#34; Bays-Durham shuffle&#34;。我从书中找到了它 Numerical Recipes 。该章的Here is a Fortran version。 Empanel格式的Here is the entire 2nd edition in Chere it is in PDF - 查找第7章第7.1节。过时版本的源代码有多种语言版本,包括Fortran(我认为),C和Pascal。几年前我下载了第2版C版文本和第1版Pascal代码,并在Pascal中使用了我自己编写的代码。