兼容性策略#
numpy.random
比 NumPy 的其余部分有更严格的兼容性策略。伪随机数的用途通常要求在给定相同种子的情况下能够精细地重现运行(即所谓的“流兼容性”),因此我们努力平衡这些需求与增强算法的灵活性。NEP 19 描述了此策略的演变。
我们强制执行的主要兼容性是在某些条件下从一次运行到另一次运行的流兼容性。如果您使用相同的 BitGenerator
和相同的种子,在相同版本的 numpy
构建中,在相同的环境下,在同一台机器上,执行相同的方法调用序列,并使用相同的参数来创建 Generator
,您应该获得相同的数字流。请注意,这些条件非常严格。NumPy 无法控制的许多因素限制了我们保证更多内容的能力。例如,不同的 CPU 实现浮点算术的方式不同,这可能导致在某些边缘情况下出现差异,并级联到流的其余部分。另一个例子是 Generator.multivariate_normal
,它使用 numpy.linalg
中的矩阵分解。即使在同一个平台上,不同版本的 numpy
构建也可能使用其链接的 LAPACK 的不同版本的矩阵分解算法,导致 Generator.multivariate_normal
返回完全不同(但同样有效!)的结果。我们力求选择更能抵抗这些影响的算法,但这总是不完美的。
注意
大多数 Generator
方法允许您从分布中抽取多个值作为数组。为此策略的目的,此数组的请求大小是一个参数。连续调用 rng.random()
5 次不保证会给出与调用 rng.random(5)
相同的结果。我们保留决定对不同大小的块使用不同算法的能力。实际上,这种情况很少发生。
与 NumPy 的其余部分一样,我们通常保持 API 源兼容性版本与版本之间的一致性。如果必须进行 API 破坏性更改,那么我们将根据 NumPy 的一般策略,仅在适当的弃用期和警告下进行。
为了在 Generator
或 default_rng
中引入新功能或提高性能而破坏流兼容性是允许的,但需谨慎。此类更改将被视为功能,因此其发布速度不会快于标准功能发布节奏(即在 X.Y
版本上,绝不会在 X.Y.Z
版本上)。为此目的,性能下降不被视为错误。破坏流兼容性的正确性错误修复可以像往常一样在错误修复版本中发生,但开发人员应考虑是否可以等到下一个功能版本。我们鼓励开发人员强烈权衡用户因流兼容性中断而带来的痛苦与改进的好处。一个值得改进的例子是改变算法以显著提高性能,例如,从高斯变量生成的 Box-Muller 变换方法转变为更快的 Ziggurat 算法。一个不鼓励的改进例子是仅仅为了小的性能改进而稍微调整 Ziggurat 表。
注意
特别是,default_rng
允许更改其使用的默认 BitGenerator
(同样,需谨慎并提前充分警告)。
通常,BitGenerator
类对版本间的流兼容性有更强的保证。这使得它们能够成为下游用户需要时更坚实的基础构件。它们有限的 API 接口使其更容易在版本之间保持这种兼容性。有关每个 BitGenerator
类的单独兼容性保证,请参阅其文档字符串。
旧版 RandomState
和 相关的便捷函数 具有更严格的版本间兼容性保证。出于 NEP 19 中概述的原因,我们在 NumPy 开发早期对它们的版本间稳定性做出了更强的承诺。对于这种兼容性,仍然有一些有限的用例(例如生成测试数据),因此我们尽可能保持兼容性。RandomState
将不再有任何修改,即使是为了修复正确性错误。在 NumPy 内部结构变化时,我们可以在一些灰色区域进行小的修复,以使 RandomState
正常工作而不发生段错误,以及一些文档字符串的修复。然而,前面提到的关于机器间和构建间可变性的警告,对于 RandomState
和 Generator
同样适用。