【问题标题】:Is there any way to generate uncorrelated random variables using Python?有没有办法使用 Python 生成不相关的随机变量?
【发布时间】:2017-05-15 11:48:00
【问题描述】:

假设我要生成两个随机变量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

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

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

【问题讨论】:

  • 你真正想用这个实现什么?
  • 您认为它们之间的关系究竟如何?给定一个x,你能推断出y 的值是多少吗?为什么你认为伪随机数不够好?
  • @tobias_k 我已经通过代码计算了 cov(X,Y)。这就是相关性的定义。
  • 这是一个估计,具有不确定性。从长远来看,即对非常长的向量进行数百万次实验,答案将收敛到零。简而言之,这就是渐近的意思。
  • @DirkEddelbuettel 每次我得到大致相同的数字,您可以自己尝试一下,看看它是否会渐近

标签: python python-3.x random


【解决方案1】:

关于 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> 

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

我们可以通过绘图使这变得更好,恢复相同的数据等等:

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")

【讨论】:

  • 不知道 random.org。看起来很有趣!
  • 您的意思是在我的代码中xy 彼此不相关?我真的怀疑,如果它们不相关,则返回值应该为零
  • 请您详细说明为什么我的猜想不正确?
  • 我真的希望您的计算机科学或数学教师不要阅读此评论。请阅读随机数生成器的测试,dieharder suite by Robert Brown et al 上的站点是一个可能的起点,还有 许多 其他的。自 1940 年代约翰·冯·诺依曼 (John von Neumann) 以来,计算机已被用于使用不相关随机数的模拟。确实有很多你可以阅读的论文和论文的图书馆。
  • 证明它们实际上是相关的那一天,你就会变得富有和成名。 (提示:你不会。)简而言之,RNG 测试可以显示不存在(或在坏的生成器情况下,存在)故障。阅读例如this piece by Marsaglia (from 1968 !!) demonstrating that an old generator was poor。遗憾的是,您关于“它在计算机上,因此具有确定性并因此具有可衡量的相关性”的结论仍然不正确。
【解决方案2】:

简答:对随机种子使用 Bays-Durham 洗牌。

更长的答案:

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

标准的线性同余调制器无法通过相关测试的主要方式是您查看由数字生成的 2 空间的一小部分区域。成对的数字在绘制时显示出明显的线条,因此并不是真正不相关的。这仅在您查看所有生成的数字对的一个非常小的区域时才重要。这是你需要做的吗?请注意,Python 的 random() 函数使用“Mersenne Twister”而不是线性同余调制器,因此这样的测试不太可能失败。请参阅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 实现,请询问,我会尽量抽出时间编写一个。在此之前,请查找“Bays-Durham shuffle”。我是从Numerical Recipes 一书中了解到的。 Here is a Fortran version 那一章。 Here is the entire 2nd edition in C 采用 Empanel 格式和 here it is in PDF--查找第 7 章第 7.1 节。过时版本的源代码有多种语言版本,包括 Fortran(我认为)、C 和 Pascal。几年前我下载了第 2 版 C 版文本和第 1 版 Pascal 代码,并将它们用于我自己的 Pascal 编码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多