兼容性策略#

numpy.random 的兼容性策略比 NumPy 的其他部分略为严格。伪随机数的使用者通常需要能够根据相同的种子(所谓的“流兼容性”)来精确重现运行,因此我们试图在满足这些需求的同时,保持算法增强的灵活性。 NEP 19 描述了此策略的演变过程。

我们强制执行的主要兼容性是在特定条件下,从一次运行到另一次运行的流兼容性。如果您使用相同的 BitGenerator、相同的种子创建 Generator,在 numpy 的相同构建版本、相同的环境中、相同的机器上,执行相同的方法调用序列并使用相同的参数,您应该会得到相同的数字流。请注意,这些条件非常严格。在 NumPy 控制之外存在许多因素,限制了我们保证比这更多的能力。例如,不同的 CPU 以不同的方式实现浮点运算,这可能导致某些边缘情况存在差异,并级联影响到数字流的其余部分。例如,Generator.multivariate_normal 使用了 numpy.linalg 的矩阵分解。即使在同一平台上,numpy 的不同构建版本也可能使用 LAPACK 的不同版本的矩阵分解算法,这会导致 Generator.multivariate_normal 返回完全不同(但同样有效!)的结果。我们努力优先选择对这些影响更具抵抗力的算法,但这始终是不完美的。

注意

大多数 Generator 方法允许您从分布中一次抽取多个值作为数组。此数组的请求大小是上述策略的一个参数。调用 5 次 rng.random() **不保证**会得到与调用 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 内部发生变化时不会出现段错误,以及一些文档字符串的修复。然而,前面提到的关于机器到机器和构建到构建的可变性的注意事项,对于 RandomStateGenerator 同样适用。