LCG 在 Kolmogorov-Smirnov 测试中是不是像我的代码所暗示的那样严重失败?

Posted

技术标签:

【中文标题】LCG 在 Kolmogorov-Smirnov 测试中是不是像我的代码所暗示的那样严重失败?【英文标题】:Does the LCG fail the Kolmogorov-Smirnov test as badly as my code suggests?LCG 在 Kolmogorov-Smirnov 测试中是否像我的代码所暗示的那样严重失败? 【发布时间】:2020-04-29 09:45:23 【问题描述】:

我用下面的Python代码给学生说明随机变量的生成:

import numpy as np
import scipy.stats as stats

def lcg(n, x0, M=2**32, a=1103515245, c=12345):
    result = np.zeros(n)
    for i in range(n):
        result[i] = (a*x0 + c) % M
        x0 = result[i]

    return np.array([x/M for x in result])

x = lcg(10**6, 3)
print(stats.kstest(x, 'uniform'))

根据 Wikipedia,默认参数是 glibc 使用的参数。打印代码的最后一行

KstestResult(statistic=0.043427751892089805, pvalue=0.0)

pvalue 0.0 表示如果x 的元素真正按照均匀分布进行分布,则观察基本上不会发生。 我的问题是:我的代码中是否存在错误,或者具有给定参数的 LCG 是否通过 10**6 副本的 Kolmogorov-Smirnov 测试?

【问题讨论】:

你使用什么版本的 Python? Python 2 和 Python 3 的除法不同 【参考方案1】:

你的代码有问题,它使分布像

我已经稍微改变了你的 LCG 实现,现在一切都很好(Python 3.7、Anaconda、Win10 x64)

import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt

def lcg(n, x0, M=2**32, a=1103515245, c=12345):
    result = np.zeros(n)
    for i in range(n):
        x0 = (a*x0 + c) % M
        result[i] = x0

    return np.array([x/float(M) for x in result])

#x = np.random.uniform(0.0, 1.0, 1000000)
x = lcg(1000000, 3)
print(stats.kstest(x, 'uniform'))

count, bins, ignored = plt.hist(x, 15, density=True)
plt.plot(bins, np.ones_like(bins), linewidth=2, color='r')
plt.show()

打印出来的

KstestResult(statistic=0.0007238884545415214, pvalue=0.6711878724246786)

和情节

更新

正如@pjs 指出的那样,你最好在循环中除以 float(M) ,不需要 第二遍遍历整个数组

def lcg(n, x0, M=2**32, a=1103515245, c=12345):
    result = np.empty(n)
    for i in range(n):
        x0 = (a*x0 + c) % M
        result[i] = x0 / float(M)

    return result

【讨论】:

【参考方案2】:

为了补充 Severin 的回答,我的代码无法正常工作的原因是 result 是一个浮点数数组。 我们可以在第二次迭代中看到两种实现之间的差异。 第一次迭代后,x0 = 3310558080

In [9]: x0 = 3310558080

In [10]: float_x0 = float(x0)

In [11]: (a*x0 + c) % M
Out[11]: 465823161

In [12]: (a*float_x0 + c) % M
Out[12]: 465823232.0

In [13]: a*x0
Out[13]: 3653251310737929600

In [14]: a*float_x0
Out[14]: 3.6532513107379297e+18

所以问题与使用浮点数有关。

【讨论】:

您的代码不起作用的原因是因为您使用了x0 = result[i] 而不是result[i] = x0 并且忽略了除以float(M) @pjs 他除以 float(M) 但最后效率很低 用更高效的实现更新了我的答案 根据我的实验,除以float(M)M 无关紧要。 @Rastapopoulos 在 python 3 中为真,在 python 2 中不为真。当 Severin 询问时,您没有指定使用哪个,float(M) 在这两种情况下都有效。

以上是关于LCG 在 Kolmogorov-Smirnov 测试中是不是像我的代码所暗示的那样严重失败?的主要内容,如果未能解决你的问题,请参考以下文章

Kolmogorov-Smirnov 测试 MATLAB 中的正态性 - 数据归一化?

Python Scipy 中的两个样本 Kolmogorov-Smirnov 测试

KS(Kolmogorov-Smirnov)(转)

在 Matlab 中执行不善的两样本 Kolmogorov-Smirnov 测试(kstest2)?

R语言Kolmogorov-Smirnov假设检验(正态性检验):检验数据的正态性

Kolmogorov-Smirnov 检验中的假设检验 - 无论是临界值还是 p 值