Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Numpy dot在对称乘法方面太聪明了_Python_Numpy_Floating Point_Linear Algebra_Floating Accuracy - Fatal编程技术网

Python Numpy dot在对称乘法方面太聪明了

Python Numpy dot在对称乘法方面太聪明了,python,numpy,floating-point,linear-algebra,floating-accuracy,Python,Numpy,Floating Point,Linear Algebra,Floating Accuracy,有人知道这种行为的文档吗 import numpy as np A = np.random.uniform(0,1,(10,5)) w = np.ones(5) Aw = A*w Sym1 = Aw.dot(Aw.T) Sym2 = (A*w).dot((A*w).T) diff = Sym1 - Sym2 差异最大值()接近机器精度非零,例如4.4e-16 这(与0的差异)通常很好。。。在一个有限精度的世界里,我们不应该感到惊讶 此外,我猜numpy在对称产品方面很聪明,以节省触发器并确

有人知道这种行为的文档吗

import numpy as np
A  = np.random.uniform(0,1,(10,5))
w  = np.ones(5)
Aw = A*w
Sym1 = Aw.dot(Aw.T)
Sym2 = (A*w).dot((A*w).T)
diff = Sym1 - Sym2
差异最大值()接近机器精度非零,例如4.4e-16

这(与0的差异)通常很好。。。在一个有限精度的世界里,我们不应该感到惊讶

此外,我猜numpy在对称产品方面很聪明,以节省触发器并确保对称输出


但我处理的是混沌系统,这个小差异在调试时很快就会变得明显。所以我想知道到底发生了什么。

我怀疑这与将中间浮点寄存器提升到80位精度有关。在某种程度上证实这一假设的是,如果我们使用较少的浮动,我们的结果始终为0,ala

A  = np.random.uniform(0,1,(4,2))
w  = np.ones(2)
Aw = A*w
Sym1 = Aw.dot(Aw.T)
Sym2 = (A*w).dot((A*w).T)
diff = Sym1 - Sym2
# diff is all 0's (ymmv)

此行为是在中为NumPy 1.11.0引入更改的结果。从1.11.0的版本:

以前,gemm-BLAS操作用于所有矩阵产品。 现在,如果矩阵积在一个矩阵和它的转置之间,它 将使用syrk BLAS操作来提高性能。这 优化已扩展到@、numpy.dot、numpy.inner和 努比·马特穆尔

在该PR的更改中,可以发现:

所以NumPy对矩阵乘以转置的情况进行了显式检查,并在这种情况下调用了不同的基础BLAS函数。正如@hpaulj在一篇评论中所指出的,这种检查对于NumPy来说是便宜的,因为转置的2d数组只是原始数组上的一个视图,具有反转的形状和跨步,因此它足以检查数组上的一些元数据(而不必比较实际的数组数据)

这里有一个稍微简单一点的例子来说明这种差异。请注意,在
dot
的一个参数上使用
.copy
就足以击败NumPy的特殊外壳

import numpy as np
random = np.random.RandomState(12345)
A = random.uniform(size=(10, 5))
Sym1 = A.dot(A.T)
Sym2 = A.dot(A.T.copy())
print(abs(Sym1 - Sym2).max())
我想,除了明显的加速潜力之外,这种特殊外壳的一个优点是,当使用
syrk
时,可以保证(我希望,但实际上这将取决于BLAS实现)得到完全对称的结果,而不是仅对称到数值误差的矩阵。作为这方面的一个(承认不是很好)测试,我尝试:

import numpy as np
random = np.random.RandomState(12345)
A = random.uniform(size=(100, 50))
Sym1 = A.dot(A.T)
Sym2 = A.dot(A.T.copy())
print("Sym1 symmetric: ", (Sym1 == Sym1.T).all())
print("Sym2 symmetric: ", (Sym2 == Sym2.T).all())
在我的机器上的结果:

Sym1 symmetric:  True
Sym2 symmetric:  False

由于您的代码将在不同的运行中提供不同的输出,请显示一个示例输出,并更清楚地说明该输出的不可取之处。您是否尝试强制使用双精度(
np.float64
)?@TomdeGeus-how?无论如何,请注意,我并不真的关心差值是否为非零。我只想解释一下这种行为(显然是因为numpy很聪明)。你可以使用
.astype(np.float64)
来定义
A
w
。顺便说一句,根据NumPy,我的机器上的机器精度是
print(np.finfo(np.float64.eps)
=2.2e-16。而
diff.max()
=1.1e-16,即在机器精度范围内。如果使用
B=Aw.T.copy()
,有任何差异吗?这是可能的。但我认为你的实验也可以用我的建议来解释:numpy以不同的方式对待对称产品。我们怎么能确定呢?我们可以确定这不是原因,因为python中间值永远不会存储80位精度,因为它们存储在内存中,而不是寄存器中。这里重要的是,
A*w
被计算了两次,而不是它是否作为一个更大的函数的一部分被计算expression@Patrick. 最可靠的方法是读取源代码。
转置
是一个连续性翻转(F连续)和跨步的
视图。因此,只需比较几个属性就可以识别它,而不需要查看任何数据(这将是非常昂贵的)。答案已更新。
Sym1 symmetric:  True
Sym2 symmetric:  False