Numpy:随机种子和多线程导致不同的结果



在python 3.7,numpy 1.17.3:上测试

使用固定种子和多线程时,使用numpy生成随机数似乎无法提供一致的结果。这个问题不是由scipy引起的。以下片段显示了问题:

import numpy as np
from scipy.stats import nbinom 
from concurrent.futures import ThreadPoolExecutor, as_completed

def load_data_np():
np.random.seed(0)
return np.random.negative_binomial(5, 0.3, size=2)
def load_data_scipy():
return nbinom.rvs(5, 0.3, size=2, random_state=0)

因此,这两种方法应该总是产生相同的数字。但是当在线程循环中生成数据时。。。

with ThreadPoolExecutor() as executor:
futures = list(
(executor.submit(load_data_np)
for i in range(1000))
)
print(np.diff([future.result() for future in as_completed(futures)]))

on可以在numpy的输出中找到这样的值:

...
[  4]
[ -3]
[-15]
[ -3]
[  5]
[ -6]
[  0]
[  6]
[  1]
[-13]
[ -7]
[  3]
[  6]
[ -2]
[ -1]
[-11]
[  3]
...

这一定意味着,在2个样本(大小=2(的后续计算之间,随机种子必须由另一个线程重置,这会使其他线程的rng计数丢失。只是将其与scipy进行比较:

with ThreadPoolExecutor(max_workers=cpu_count()) as executor:
futures = list(
(executor.submit(load_data_scipy)
for i in range(1000))
)
print(np.diff([future.result() for future in as_completed(futures)]))

每次迭代都产生相同的值

...
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
[-11]
...

那么,在numpy中使用固定种子的线程安全rng的正确方法是什么呢?在谷歌上搜索这个问题让我回到了np.random.seed.

干杯,Michael

我修改了您的load_data_np方法,使其不使用np.random.seed

正如我在其他一些SO线程中发现的那样,已知seed不是线程安全的,建议使用您自己的RandomState实例。

def load_data_np():
rs = np.random.RandomState(0)
return rs.negative_binomial(5, 0.3, size=2)

现在的输出看起来和预期的一样

...
[-11]
[-11]
[-11]
[-11]
[-11]
...

这应该会有所帮助。

最新更新