【问题标题】:Why is numpy random seed not remaining fixed but RandomState is when run in parallel?为什么 numpy 随机种子没有保持固定,但 RandomState 在并行运行时是固定的?
【发布时间】:2020-03-25 02:50:05
【问题描述】:

我正在使用 joblib 并行运行 蒙特卡罗模拟。然而,我注意到虽然我的种子是固定的,但我的结果一直在变化。但是,当我按顺序运行该过程时,它保持不变。

下面我实现了一个小例子,模拟具有较高方差的正态分布的均值。

加载库并定义函数

import numpy as np
from joblib import Parallel, delayed

def _estimate_mean():
    np.random.seed(0)
    x = np.random.normal(0, 2, size=100)
    return np.mean(x)

系列实现的第一个示例 - 结果都与预期相同。

tst = [_estimate_mean() for i in range(8)]
In [28]: tst
Out[28]:
[0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897]

并行实现的第二个例子:(注意有时手段都是一样的,其他时候不是)

tst = Parallel(n_jobs=-1, backend="threading")(delayed(_estimate_mean)() for i in range(8))

In [26]: tst
Out[26]:
[0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.1640259414956747,
 -0.11846452111932627,
 -0.3935934130918206]

我希望并行运行与固定种子相同。我发现如果我实施RandomState 来修复种子,它似乎可以解决问题:

def _estimate_mean():
    local_state = np.random.RandomState(0)
    x = local_state.normal(0, 2, size=100)
    return np.mean(x)
tst = Parallel(n_jobs=-1, backend="threading")(delayed(_estimate_mean)() for i in range(8))

In [28]: tst
Out[28]:
[0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897,
 0.11961603106897]

在使用numpy.random 修复种子时,使用RandomState 和仅使用seed 有什么区别,为什么后者在并行运行时不能可靠地工作?

系统信息

操作系统:Windows 10

Python:3.7.3(默认,2019 年 4 月 24 日,15:29:51)[MSC v.1915 64 位 (AMD64)]

Numpy:1.17.2

【问题讨论】:

标签: python numpy parallel-processing random-seed


【解决方案1】:

您使用numpy.random.* 获得的结果是由于竞态条件 而发生的。 numpy.random.* 仅使用一个全局 PRNG,它在所有线程之间共享而无需同步。由于线程同时并行运行,并且它们对这个全局 PRNG 的访问在它们之间不同步,所以它们都在竞相访问 PRNG 状态(因此 PRNG 的状态可能会在其他线程的背后发生变化)。为每个线程提供自己的 PRNG (RandomState) 解决了这个问题,因为不再有任何状态在没有同步的情况下由多个线程共享。


既然您使用的是 NumPy 1.17,您应该知道还有一个更好的选择:NumPy 1.17 引入了new random number generation system;它使用所谓的bit generators,例如PCG,以及random generators,例如新的numpy.random.Generator

这是proposal to change the RNG policy 的结果,它指出通常不应再使用numpy.random.* 函数。这尤其是因为numpy.random.* 在全局状态下运行。

NumPy 文档现在包含关于——

的详细信息

在新的 RNG 系统中。另请参阅“Seed Generation for Noncryptographic PRNGs”,来自我的一篇文章,其中包含有关 RNG 选择的一般建议。

【讨论】:

    猜你喜欢
    • 2020-02-21
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 2017-03-02
    • 2015-02-19
    • 2020-08-27
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多