兼容性策略#
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 策略进行适当的弃用期和警告。
为了引入新功能或提高Generator
或default_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
一样。