【问题标题】:Does scipy.stats produce different random numbers for different computer hardware?scipy.stats 是否为不同的计算机硬件产生不同的随机数?
【发布时间】:2019-03-04 13:13:17
【问题描述】:

我遇到了一个问题,尽管我在不同的计算机上获得了不同的随机数

  • scipy.__version__ == '1.2.1' 在所有计算机上
  • numpy.__version__ == '1.15.4' 在所有计算机上
  • random_state seed 在每个生成随机数以获得可重复结果的函数调用中都固定为相同的数字 (42)

在此处完整发布代码有点复杂,但我注意到在从多元法线采样时结果开始出现分歧:

import numpy as np
from scipy import stats
seed = 42
n_sim = 1000000
d = corr_mat.shape[0] # corr_mat is a 15x15 correlation matrix, numpy.ndarray
# results diverge from here across different hardware
z = stats.multivariate_normal(mean=np.zeros(d), cov=corr_mat).rvs(n_sim, random_state=seed)

corr_mat 是一个相关矩阵(见下面的附录),在所有计算机上都是相同的。

我们正在测试的两台不同的计算机是

计算机 1


  • 操作系统:Windows 7
  • 处理器:Intel(R) Xeon(R) CPU E5-2623 v4 @ 2.60Ghz 2.60 Ghz(2 个处理器)
  • 内存:64 GB
  • 系统类型:64 位

计算机 2


  • 操作系统:Windows 7
  • 处理器:Intel(R) Xeon(R) CPU E5-2660 v3 @ 2.10Ghz 2.10 Ghz(2 个处理器)
  • 内存:64 GB
  • 系统类型:64 位

附录

corr_mat
>>> array([[1.  , 0.15, 0.25, 0.25, 0.25, 0.25, 0.1 , 0.1 , 0.1 , 0.25, 0.25,
        0.25, 0.1 , 0.1 , 0.1 ],
       [0.15, 1.  , 0.  , 0.  , 0.  , 0.  , 0.15, 0.05, 0.15, 0.15, 0.15,
        0.  , 0.15, 0.15, 0.15],
       [0.25, 0.  , 1.  , 0.25, 0.25, 0.25, 0.2 , 0.  , 0.2 , 0.2 , 0.2 ,
        0.25, 0.2 , 0.2 , 0.2 ],
       [0.25, 0.  , 0.25, 1.  , 0.25, 0.25, 0.2 , 0.  , 0.2 , 0.2 , 0.2 ,
        0.25, 0.2 , 0.2 , 0.2 ],
       [0.25, 0.  , 0.25, 0.25, 1.  , 0.25, 0.2 , 0.  , 0.2 , 0.2 , 0.2 ,
        0.25, 0.2 , 0.2 , 0.2 ],
       [0.25, 0.  , 0.25, 0.25, 0.25, 1.  , 0.2 , 0.  , 0.2 , 0.2 , 0.2 ,
        0.25, 0.2 , 0.2 , 0.2 ],
       [0.1 , 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 1.  , 0.15, 0.25, 0.25, 0.25,
        0.2 , 0.25, 0.25, 0.25],
       [0.1 , 0.05, 0.  , 0.  , 0.  , 0.  , 0.15, 1.  , 0.15, 0.15, 0.15,
        0.  , 0.15, 0.15, 0.15],
       [0.1 , 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 1.  , 0.25, 0.25,
        0.2 , 0.25, 0.25, 0.25],
       [0.25, 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 0.25, 1.  , 0.25,
        0.2 , 0.25, 0.25, 0.25],
       [0.25, 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 0.25, 0.25, 1.  ,
        0.2 , 0.25, 0.25, 0.25],
       [0.25, 0.  , 0.25, 0.25, 0.25, 0.25, 0.2 , 0.  , 0.2 , 0.2 , 0.2 ,
        1.  , 0.2 , 0.2 , 0.2 ],
       [0.1 , 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 0.25, 0.25, 0.25,
        0.2 , 1.  , 0.25, 0.25],
       [0.1 , 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 0.25, 0.25, 0.25,
        0.2 , 0.25, 1.  , 0.25],
       [0.1 , 0.15, 0.2 , 0.2 , 0.2 , 0.2 , 0.25, 0.15, 0.25, 0.25, 0.25,
        0.2 , 0.25, 0.25, 1.  ]])

【问题讨论】:

  • 您是否尝试过将百万法线转储到一个文件中并从两个平台对文件进行比较,而不是诸如相关性之类的间接措施,这可能有其自身平台相关的实现问题?跨度>
  • 是的,这就是我最初所做的,这使我看到了上面的代码 - 差异显示两组普通 rv 在两台计算机上是不同的。但现在我不知道为什么。奇怪的是,我什至为 stats.multivariate_normal 创建了一个较小尺寸 (2x2) corr matt 的测试,它在两台计算机上产生相同的结果。问题可能出在我上面的 15x15 corr_mat 上,但我已经检查过,两台计算机上都是一样的
  • 从相关多正态抽样涉及我相信协方差矩阵的分解。我想这是你观察到的分歧的一个候选来源。

标签: python numpy random scipy hardware


【解决方案1】:

以下是有根据的猜测,由于我没有多台机器,我无法验证。

从相关多正态采样通常是通过从不相关的标准正态采样然后乘以协方差矩阵的“平方根”来完成的。如果我使用 identity(15) 代替协方差,然后乘以 l*sqrt(d) 其中 l,d,r = np.linalg.svd(covariance)

我认为 SVD 足够复杂,可以解释平台之间的细微差异。

这个滚雪球怎么会变成有意义的事情?

我认为你选择的协方差矩阵是罪魁祸首,因为它具有非唯一的特征值。因此,SVD 不是唯一的,因为可以旋转给定多个特征值的特征空间。这有可能极大地放大微小的数值差异。

如果您使用具有唯一特征值的不同协方差矩阵进行测试,看看您看到的差异是否仍然存在会很有趣。

编辑

作为参考,这是我为您的较小 (6D) 示例尝试的:

>>> cm6 = np.array([[1,.5,.15,.15,0,0], [.5,1,.15,.15,0,0],[.15,.15,1,.25,0,0],[.15,.15,.25,1,0,0],[0,0,0,0,1,.1],[0,0,0,0,.1,1]])
>>> ls6,ds6,rs6 = np.linalg.svd(cm6)
>>> np.random.seed(42)
>>> cs6 = stats.multivariate_normal(cov=cm6).rvs()
>>> np.random.seed(42)
>>> is6 = stats.multivariate_normal(cov=np.identity(6)).rvs()
>>> LS6 = ls6*np.sqrt(ds6)
>>> np.allclose(cs6, LS6@is6)
True

正如您报告的那样,问题仍然存在于唯一的特征值中,这是另一种可能性。上面我使用svd 来计算特征向量/值,这是可以的,因为 cov 是对称的。如果我们改用eigh 会发生什么?

>>> de6,le6 = np.linalg.eigh(cm6)
>>> LE6 = le6*np.sqrt(de6)
>>> cs6
array([-0.00364915, -0.23778611, -0.50111166, -0.7878898 , -0.91913994,
        1.12421904])
>>> LE6@is6
array([ 0.54338614,  1.04010029, -0.71379193, -0.88313042, -0.60813547,
        0.26082989])

这些是不同的。为什么?首先,eigh 反过来对特征空间进行排序:

>>> ds6
array([1.7 , 1.1 , 1.05, 0.9 , 0.75, 0.5 ])
>>> de6
array([0.5 , 0.75, 0.9 , 1.05, 1.1 , 1.7 ])

这样可以解决吗?差不多了。

>>> LE6[:, ::-1]@is6
array([-0.00364915, -0.23778611, -0.50111166, -0.7878898 , -1.12421904,
        0.91913994])

我们看到最后两个样本被交换并且它们的符号被翻转。原来这是由于一个特征向量的符号被反转了。

因此,即使对于唯一的特征值,由于 (1) 特征空间的顺序和 (2) 特征向量的符号存在歧义,我们也会得到很大的差异。

【讨论】:

  • 知道这是一个问题非常有趣,感谢您指出这一点。我认为如果协方差矩阵是半正定的,那就足够了。虽然,即使使用具有唯一特征值的协方差矩阵,我的问题仍然存在(我尝试了 array([[1,.5,.15,.15,0,0], [.5,1,.15,.15, 0,0],[.15,.15,1,.25,0,0],[.15,.15,.25,1,0,0],[0,0,0,0,1, .1],[0,0,0,0,.1,1]]))。我怀疑此时这可能是不同版本的 MKL / BLAS / LAPACK 的问题。再次感谢!
  • 伟大的编辑。在我的计算机上玩了一些并确保库都是相同的版本之后,我发现问题没有持续存在,使用具有唯一特征值的小型 6d 矩阵。我想这意味着问题必须如您所建议的那样,SVD 不是唯一的。很高兴知道这是测试随机模型时的一个潜在问题。我不明白的最后一件事是,如果 SVD 不是唯一的,为什么我总是在一台计算机上得到相同的结果,但在不同的计算机上得到不同的结果 - 这绝对不是硬件吗?
  • @PyRsquared :有多种原因。其中包括以不同顺序完成的并行运算、浮点数学实现之间的差异(尤其是在不强制实现尽可能准确的结果的情况下)以及以不同顺序执行的浮点运算。当应用程序需要可重复的“随机性”时,应避免生成“随机”浮点数(或至少使用复杂算法这样做)。另请参阅我的相关文章中的footnote
  • @PyRsquared re: “为什么我总是在一台计算机上得到相同的结果” 实现是确定性的,这是完全合理的,所以所有事情都是平等的相同的答案。但是,一旦在某处存在微小差异,最终结果就会看起来非常不同。我认为(但我绝对不是这方面的专家,在这里可能是错误的)硬件版本确实可以对浮点运算引入微小的变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多