在Python中生成多个独立的随机流

11

我希望在Python中生成多个随机数流。我正在编写一个用于模拟队列系统的程序,希望有一个流用于到达时间,另一个流用于服务时间等。

numpy.random() 从全局流中生成随机数。

在Matlab中有称为RandStream的东西,它使我能够创建多个流。

是否有办法在Python中创建类似于RandStream的东西?


你是出于方差降低的目的吗? - pjs
5个回答

17

Numpy和内部随机生成器都有可实例化的类。

对于只使用random

import random
random_generator = random.Random()
random_generator.random()
#>>> 0.9493959884174072

对于Numpy:

import numpy
random_generator = numpy.random.RandomState()
random_generator.uniform(0, 1, 10)
#>>> array([ 0.98992857,  0.83503764,  0.00337241,  0.76597264,  0.61333436,
#>>>         0.0916262 ,  0.52129459,  0.44857548,  0.86692693,  0.21150068])

2
@Atcold "这个模块提供的函数实际上是一个隐藏实例 random.Random 类的绑定方法。您可以实例化自己的 Random 实例来获得不共享状态的生成器。" - https://docs.python.org/3/library/random.html - Veedrac
但是如何生成独立的流?连续的种子是否保证有效? - Praveen
@Praveen 如果你只是想要不同的流,请使用 random.Random()。如果你想为可重现性进行种子处理,则任何不同的种子都可以。 - Veedrac
1
@RafaelAlmeida 这是一个病态的例子,而且这里有几个原因不适用。1)我们只生成两个序列,所以这些序列很快就会失去相关性,而不是从许多连续序列中取样一个样本,2)Python的种子生成具有哈希步骤来修复相关性,3)你永远不会从像Mersenne Twister这样的平庸生成器中获得理想的独立性;使用更好的随机数生成器(最好是加密的),如果有问题就不要使用固定的种子。我同意使用更大、更高熵的种子更具风险规避性。 - Veedrac
1
值得注意的是,C#似乎正在使用减法生成器,看起来很糟糕。 - Veedrac
显示剩余2条评论

2
您不需要使用RandomGen包。只需初始化两个流即可。例如:
import numpy as np
prng1 = np.random.RandomState()
prng2 = np.random.RandomState()
prng1.seed(1)
prng2.seed(1)

现在,如果您使用 prngX.rand() 推进这两个流,您会发现两个流将给出相同的结果,这意味着它们是带有相同种子的独立流。
要使用 random 包,只需将 np.random.RandomState() 替换为 random.Random() 即可。

1
为了使结果可重现,您可以直接向random.Random()传递种子,然后从那里调用变量。每个初始化的实例将独立于其他实例运行。例如,如果您运行:
import random
rg1 = random.Random(1)
rg2 = random.Random(2)
rg3 = random.Random(1)
for i in range(5): print(rg1.random())
print('')
for i in range(5): print(rg2.random())
print('')
for i in range(5): print(rg3.random())

你将获得:

0.134364244112
0.847433736937
0.763774618977
0.255069025739
0.495435087092

0.956034271889
0.947827487059
0.0565513677268
0.0848719951589
0.835498878129

0.134364244112
0.847433736937
0.763774618977
0.255069025739
0.495435087092

0

numpy 添加了使用 SeedSequence 生成独立随机数流的功能。该过程会处理用户提供的种子,通常是某个大小的整数,并将其转换为 BitGenerator 的初始状态。它使用哈希技术确保低质量的种子被转换为高质量的初始状态(至少在非常高的概率下)。

from numpy.random import SeedSequence, default_rng

ss = SeedSequence(12345)

# Spawn off 10 child SeedSequences to pass to child processes.
child_seeds = ss.spawn(10)
streams = [default_rng(s) for s in child_seeds]

每个流都是PCG64生成器。可以按顺序生成随机数,如下所示 -
for i in 1:K
    instance[i] = [s.uniform() for s in streams]

有更多的方法可以生成独立的随机数流,请查看numpydocs


0

Veedrac的回答没有解决如何生成独立流的问题。

我找到的最好的方法是使用numpy的RandomState的替代品。这由RandomGen包提供。

它支持独立随机流, 但这些使用三个随机数生成器之一:PCG64、ThreeFry或Philox。如果你想使用更传统的MT19937,你可以依靠跳跃


random.Random() 是一个独立的流,至少在 Mersenne Twister 的限制范围内是这样。如果你需要 n 个流,请使用 [random.Random() for _ in range(n)] - Veedrac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接