为什么使用numpy.random.seed不是一个好习惯?

Gab*_*zer 5 python random numpy random-seed

我想做使用随机数作为输入的可重复测试。我习惯在Matlab中调用rng,在Python中调用numpy.random.seed。但是,我注意到种子帮助的“注释”部分显示为:

这是一种便利的传统功能。

最佳实践是不要播种BitGenerator,而要重新创建一个新的BitGenerator。由于遗留原因,此处使用此方法。此示例演示了最佳实践。

from numpy.random import MT19937
from numpy.random import RandomState, SeedSequence
rs = RandomState(MT19937(SeedSequence(123456789)))  
# Later, you want to restart the stream
rs = RandomState(MT19937(SeedSequence(987654321)))
Run Code Online (Sandbox Code Playgroud)

与文档字符串建议相比,有人知道使用种子的注意事项吗?

小智 7

来自https://numpy.org/neps/nep-0019-rng-policy.html

获得可重复伪随机数的首选最佳实践是使用种子实例化生成器对象并将其传递。numpy.random.* 便利函数背后的隐式全局 RandomState 可能会导致问题,尤其是在涉及线程或其他形式的并发时。全局状态总是有问题的。当涉及可重复性时,我们断然建议避免使用便利函数。

也就是说,人们确实使用它们并使用 numpy.random.seed() 来控制它们下面的状态。可能很难一致且有用地对 API 使用进行分类和计数,但一个非常常见的用法是在单元测试中,其中许多全局状态问题的可能性较小。

本 NEP 不建议删除这些功能或更改它们以使用不太稳定的 Generator 分发实现。未来的 NEP 可能会。

具体来说,新 PRNG 子系统的初始版本应将这些便利函数作为全局 RandomState 上的方法的别名,该方法使用 Mersenne Twister BitGenerator 对象进行初始化。对 numpy.random.seed() 的调用将被转发到该 BitGenerator 对象。此外,在这个初始版本中,全局 RandomState 实例必须可以通过名称 numpy.random.mtrand._rand 访问:Robert Kern 很久以前向 scikit-learn 承诺这个名称将是稳定的。哎呀。

为了允许某些变通方法,必须可以将全局 RandomState 下的 BitGenerator 替换为任何其他 BitGenerator 对象(我们将精确的 API 细节留给新子系统)。此后调用 numpy.random.seed() 应该只是将给定的种子传递给当前的 BitGenerator 对象,而不是尝试将 BitGenerator 重置为 Mersenne Twister。numpy.random.* 便利函数集应保持与当前相同。它们应该是 RandomState 方法的别名,而不是新的不太稳定的分布类(生成器,在上面的例子中)。想要获得最快、最佳分布的用户可以遵循最佳实践并显式实例化生成器对象。

本 NEP 不建议永久保留这些要求。在我们体验了新的 PRNG 子系统之后,我们可以而且应该在未来的 NEP 中重新审视这些问题。