从 1 个值播种 N 个独立随机数生成器的最佳方法

机器算法验证 Python 蒙特卡洛 随机生成 麻木的
2022-03-06 02:49:00

在我的程序中,我需要运行 N 个单独的线程,每个线程都有自己的 RNG,用于对大型数据集进行采样。我需要能够用一个单一的值来播种整个过程,这样我才能重现结果。

简单地依次增加每个索引的种子就足够了吗?

目前我使用numpy's RandomState,它使用 Mersenne Twister 伪随机数生成器。

下面的代码片段:

# If a random number generator seed exists
if self.random_generator_seed:
    # Create a new random number generator for this instance based on its
    # own index
    self.random_generator_seed += instance_index
    self.random_number_generator = RandomState(self.random_generator_seed)

本质上,我从用户输入的种子(如果存在)开始,对于每个实例/线程,我依次添加正在运行的实例的索引(0 到 N-1)。我不知道这是否是好的做法,或者是否有更好的方法来做到这一点。

4个回答

当然,这不是很好的做法。例如,考虑使用根种子 12345 和 12346 进行两次运行时会发生什么。每次运行都会有N-1共同的流。

Mersenne Twister 实现(包括numpy.randomrandom)通常使用不同的 PRNG 将整数种子扩展为 MT 使用的大状态向量(624 个 32 位整数);这是来自 的数组RandomState.get_state()做你想做的事的一个好方法是运行那个 PRNG,用你的输入整数播种一次,并从中获取N*62432 位整数。将该流拆分为N状态向量并用于RandomState.set_state()显式初始化每个RandomState实例。您可能必须查阅标准库的 C 源代码numpy.random_random从标准库获取该 PRNG(它们是相同的)。我不确定是否有人为 Python 实现了该 PRNG 的独立版本。

用于并行处理的解决方案是使用您的随机生成器Φ(u), 在哪里u是你的种子,通过N-批次:

  1. 产生Φ(u),ΦN(u),Φ2N(u),...
  2. 产生Φ2(u),Φ1+N(u),Φ1+2N(u),...
  3. ...
  4. 产生ΦN1(u),ΦN1+N(u),ΦN1+2N(u),...

在哪里Φn(u)=Φ(Φn1(u)). 通过这种方式,您使用单个种子,并且您的序列都是统一且独立的。

现在有一个名为RandomGen的 Python 包,它具有实现此目的的方法。

支持从单个种子创建的独立流,以及用于旧随机数生成器(如 MT19937)的跳跃协议。

一些人声称,顺序种子产生的随机数存在相关性。https://stackoverflow.com/questions/10900852/near-seeds-in-random-number-generation-may-give-similar-random-numbers我不确定这是多么真实。

如果您对此感到担心,为什么不使用单个随机数生成器来为所有其他生成器选择种子呢?