【问题标题】:Does Python random.seed() and numpy.random.seed() implementations differ one from another?Python random.seed() 和 numpy.random.seed() 实现是否彼此不同?
【发布时间】:2020-06-02 04:10:42
【问题描述】:

我正在尝试实现 CLT(中心极限定理)时数据分布的差异,比较两种方法:一种使用纯 Python,另一种使用 Numpy。

这是我的代码:

from numpy.random import seed
from numpy.random import randint
from numpy import mean
import matplotlib.pyplot as plt
import random

# [With Numpy]
#
# Generate 1000 samples of 50 men, from 60 to 90 Kilos and calculate the mean
# of each sample, at once.
seed(1)
means = [mean(randint(60, 90, 50)) for _i in range(1000)]

# [Without Numpy]
#
# Generate 1000 samples of 50 men, from 60 to 90 Kilos.
# Calculate the mean of each sample, storing on a separated list.
random.seed(1)
samples = list()
for i in range(0, 1000):
    samples.append([random.randint(60, 90) for n in range(50)])
means_without_numpy = [sum(s) / len(s) for s in samples]

# Plot distributions of sample means, side by side.
plt.subplot(1, 2, 1)
plt.title("Numpy")
plt.hist(means)
plt.subplot(1, 2, 2)
plt.title("Pure Python")
plt.hist(means_without_numpy)
plt.show()

print(f"The mean of means:                 {mean(means)}")
print(f"The mean of means (without numpy): {mean(means_without_numpy)}")   

此代码在关闭它们后会生成以下直方图和一条消息:

$ python3 clt_comparisson.py 
The mean of means:                74.54001999999998
The mean of means (without numpy): 74.94394

我的问题是:

  1. 分布(来自随机数据集的平均值)是否受到每个模块(randomnumpy)提供随机数据的方式的影响?
  2. 如果第一个问题是正确的:既然我提供 1 作为种子,它们是否应该生成相同的随机数据集,因为它们具有相同的种子值?

【问题讨论】:

  • “它们是否应该生成相同的随机数据集,因为它们具有相同的种子值” - 不,这不是播种的工作原理。
  • 种子(按范围或值)并不意味着使用相同的 PRNG 算法。决定序列质量的是实际算法。 - en.wikipedia.org/wiki/Pseudorandom_number_generator
  • @user2357112supportsMonica - 使用相同种子两次的相同算法应该产生相同的结果。创建r1 = random.Random(b'My standard seed')r2 = random.Random(b'My standard seed'),两者都会产生相同的数字。 r1.randint(0, 100000) == r2.randint(0, 100000).

标签: python numpy matplotlib random random-seed


【解决方案1】:

numpy 和 python 的random 使用不同的算法,我认为这对于用 C 和 fortran 编写的数学包来说是非常值得期待的。具有相同种子的相同算法将产生相同的值

>>> import random
>>> random.seed(12345678)
>>> import numpy.random
>>> numpy.random.seed(12345678)
>>> random.randint(0, 100000)
94406
>>> numpy.random.randint(0, 100000)
67251

(不一样)

即使在很大范围内,两种实现之间的分布也会略有不同,因为您不会期望它们之间的随机性质量完全相同。如果您在同一个程序中创建第二个数据集而不更改种子,它会有所不同,具有不同种子的数据集也是如此。

人们不会在加密环境中提供自己的种子,但在科学方面,如果您希望模型可重现,它会很有用。在这种情况下,将您的代码基于 numpy.random.RandState 并使用一些众所周知的 32 整数,这样您就不必担心其他人可能需要或可以更改的程序范围内的 numpy.random.seed()

【讨论】:

  • 可能值得注意的是,两种情况下的底层 PRNG 是相同的:它是 Mersenne Twister。播种和随机整数生成的细节是不同的。此外,random.randint 不适合 numpy.random.randint - 前者包括上端点,而后者不包括。
  • 最后,从 NumPy 1.18 开始,numpy.random.randint 不再是生成整数的推荐方式;见numpy.org/doc/stable/reference/random/…。使用默认随机 NumPy 生成器的新方法,确实使用与核心 Python 完全不同的 PRNG。 (PCG64 变体。)
  • @MarkDickinson -感谢您提供的信息。我假设由于 numpy 使用 32 位无符号整数,它正在消失在一些基于 fortran 的旧 rng 的内部。现在我知道到底发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2015-02-07
  • 2021-08-04
  • 2015-09-12
相关资源
最近更新 更多