在 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)]))
可以在 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。
干杯, 迈克尔
最佳答案
我修改了您的 load_data_np
方法,使其不使用 np.random.seed
。
正如我在其他一些文章中发现的那样 SO thread 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]
...
这应该有帮助。
关于python - Numpy:随机种子和多线程导致不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58875076/