为什么在并行运行时numpy随机种子不能保持固定,但是RandomState是?
问题内容:
我正在使用并行运行 蒙特卡洛模拟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]
我 在Parallel中 实现的第二个示例:(请注意,有时均值相同,有时不一样)
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]
使用
RandomState
和Justseed
固定种子时有什么区别numpy.random
?为什么在并行运行时种子不能可靠地工作?
系统信息
作业系统:Windows 10
Python:3.7.3(默认值,2019年4月24日15:29:51)[MSC v.1915 64位(AMD64)]
脾气暴躁:1.17.2
问题答案:
numpy.random.*
由于 比赛条件,
您获得的结果正在发生。numpy.random.*
仅使用一个在所有线程之间共享的全局PRNG,而无需同步。由于线程同时并行运行,并且它们对全局PRNG的访问未在它们之间同步,因此它们都竞相访问PRNG状态(因此PRNG的状态可能在其他线程的支持下改变)。为每个线程提供自己的PRNG(RandomState
)解决了此问题,因为不再有任何状态在不同步的情况下被多个线程共享。
由于您使用的是NumPy 1.17,因此您应该知道还有更好的选择:NumPy
1.17引入了新的随机数生成系统;它使用诸如PCG之类的所谓
位生成器 ,以及诸如new之类的 随机生成器numpy.random.Generator
。
这是一项更改RNG政策的建议的结果,该政策指出numpy.random.*
通常不应再使用功能。这尤其是因为numpy.random.*
在全局状态下运行。
NumPy文档现在具有有关以下内容的详细信息:
在新的RNG系统中。另请参阅我的文章中的“非加密PRNG的种子生成”,其中包含有关RNG选择的一般建议。