兼容性策略#

numpy.random 具有比 NumPy 其余部分更严格的兼容性策略。伪随机数的用户通常在使用情况下需要能够在给定相同种子时精确地重现运行(所谓的“流兼容性”),因此我们尝试在这些需求与增强算法的灵活性之间取得平衡。NEP 19 描述了此策略的演变。

我们执行的主要兼容性类型是在某些条件下跨运行的流兼容性。如果您使用相同的 BitGenerator 和相同的种子创建 Generator,使用相同的参数执行相同的系列方法调用,在相同的 numpy 版本上,在相同的环境中,在相同的机器上,您应该获得相同的数字流。请注意,这些条件非常严格。NumPy 控制范围之外的一些因素限制了我们保证更多内容的能力。例如,不同的 CPU 以不同的方式实现浮点运算,这会导致某些极端情况下的差异,并级联到流的其余部分。Generator.multivariate_normal 举另一个例子,它使用来自 numpy.linalg 的矩阵分解。即使在同一个平台上,不同的 numpy 版本也可能使用来自其链接的 LAPACK 的此矩阵分解算法的不同版本,从而导致 Generator.multivariate_normal 返回完全不同的(但同样有效!)结果。我们努力优先考虑对这些影响更具抵抗力的算法,但这始终是不完美的。

注意

大多数 Generator 方法允许您从分布中以数组的形式绘制多个值。此数组的请求大小是一个参数,用于上述策略的目的。调用 rng.random() 5 次**不保证**会给出与 rng.random(5) 相同的数字。我们保留决定对不同大小的块使用不同算法的权利。在实践中,这种情况很少发生。

与 NumPy 的其余部分一样,我们通常在版本之间保持 API 源代码兼容性。如果我们**必须**进行破坏 API 的更改,那么我们将仅按照 NumPy 通用策略 在适当的弃用期限和警告下进行。

为了引入新功能或提高 Generatordefault_rng 中的性能,**允许**破坏流兼容性,但要**谨慎**。此类更改将被视为功能,因此其速度不会快于功能的标准发布节奏(即在 X.Y 版本上,而不是 X.Y.Z)。出于此目的,速度缓慢不被视为错误。破坏流兼容性的正确性错误修复可以按照惯例在错误修复版本中进行,但开发人员应考虑他们是否可以等到下一个功能版本。我们鼓励开发人员权衡流兼容性中断给用户带来的痛苦与改进。值得改进的一个例子是更改算法以显著提高性能,例如,从高斯变量生成的 Box-Muller 变换 方法切换到更快的 Ziggurat 算法。不鼓励改进的一个例子是对 Ziggurat 表进行微调以获得较小的性能改进。

注意

特别是,default_rng 允许更改其使用的默认 BitGenerator(同样,要**谨慎**并提前发出大量警告)。

总的来说,BitGenerator 类对版本间流兼容性有更强的保证。这使得它们成为需要它的下游用户的更坚实的基础构建块。它们有限的 API 表面使它们更容易在版本之间保持这种兼容性。有关其各自的兼容性保证,请参阅每个 BitGenerator 类的文档字符串。

遗留的 RandomState相关的便利函数 具有更严格的版本间兼容性保证。由于 NEP 19 中概述的原因,我们在 NumPy 开发的早期对它们的版本间稳定性做出了更强有力的承诺。这种兼容性仍然有一些有限的用例(例如生成测试数据),因此我们尽可能保持兼容性。将不再对 RandomState 进行任何修改,甚至不会修复正确性错误。有一些灰色地带,我们可以进行一些小的修复以保持 RandomState 在 NumPy 内部发生变化时不会发生段错误,以及一些文档字符串修复。但是,前面提到的关于机器到机器和版本到版本的可变性的警告同样适用于 RandomState,就像它适用于 Generator 一样。