Python 小圆点问题
我正在使用NumPy中的点函数来执行矩阵乘法 如果我正确理解矩阵乘法,则以下所有方法应给出完全相同的输出:Python 小圆点问题,python,numpy,matrix-multiplication,Python,Numpy,Matrix Multiplication,我正在使用NumPy中的点函数来执行矩阵乘法 如果我正确理解矩阵乘法,则以下所有方法应给出完全相同的输出: print(L.dot(Linv)[3,9]) # 1.6335244394160178 print((L @ Linv)[3,9]) # 1.6335244394160178 print(np.einsum("ab,bc->ac", L, Linv)[3,9]) # 0.0 print(np.sum(L[3,:] * Linv[:, 9])) # 0.0 然而
print(L.dot(Linv)[3,9]) # 1.6335244394160178
print((L @ Linv)[3,9]) # 1.6335244394160178
print(np.einsum("ab,bc->ac", L, Linv)[3,9]) # 0.0
print(np.sum(L[3,:] * Linv[:, 9])) # 0.0
然而,我得到了不同的输出。numpy的@和点函数到底在做什么?指南中指出,如果参数是矩阵,则执行矩阵乘法
我在这里添加脚本的要点以重现结果(L和Linv数据):
编辑:
我在Ubuntu 20.04上,使用Anaconda和python 3.8.5(GCC 7.3.0),numpy 1.19.2:
np.show\u config()
的结果是
blas_mkl_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/darth-vader/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/darth-vader/anaconda3/include']
blas_opt_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/darth-vader/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/darth-vader/anaconda3/include']
lapack_mkl_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/darth-vader/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/darth-vader/anaconda3/include']
lapack_opt_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/darth-vader/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/darth-vader/anaconda3/include']
使用示例数组(复制和粘贴字符串很好):
对于所有[3,9]元素,我得到0
In [90]: np.allclose(X.dot(Y),X@Y)
Out[90]: True
In [91]: np.allclose(X.dot(Y),np.einsum('ab,bc->ac',X,Y))
Out[91]: True
In [92]: (X@Y)[3,9]
Out[92]: 0.0
我想我找到了问题所在,
文本或python安装没有问题,但这是矩阵本身的问题。
通过替换
# Write the data
fp = open("_L_", "w")
fp.write(L)
fp.close()
fp = open("_Linv_", "w")
fp.write(Linv)
fp.close()
# Load them as numpy array
L = np.loadtxt("_L_")
Linv = np.loadtxt("_Linv_")
与:
问题解决了(两者给出相同的结果,不同于双精度获得的结果)。事实上,Linv的元件大到1e17,这是双精度数值精度的极限。
因此,如果通过按不同顺序对元素求和来执行逐列矩阵乘法,则截断错误的作用将不同。这就是为什么np.dot和matmul给出与einsum和sum不同的结果的原因
我认为,在某些numpy版本中,其原因可能取决于blas、lapack和mkl的配置,这可能会改变dot和matmul函数的行为。这确实是有关联的。我尝试用anaconda更新到numpy的最新版本,但它仍然给了我错误的答案(dot和einsum结果之间的allclose对我来说是错误的,dot给出了错误的结果,形状是正确的)。是否存在一个numpy测试套件来检查一切是否正常工作?我认为python/numpy iInstallation没有任何问题。关于数组,文本版本无法传达某些信息。您是否在新的python会话中测试过该代码?我的机器直接运行linux/pip安装,我想这是因为我有anaconda版本的numpy,安装了MKL库。通过这种方式,numpy的点函数以不同的方式实现,以利用多处理,这就是我们的结果不同的原因。您使用的是什么操作系统?
np.show\u config()
显示了什么?@Eric我在python版本的答案中添加了详细信息。
In [90]: np.allclose(X.dot(Y),X@Y)
Out[90]: True
In [91]: np.allclose(X.dot(Y),np.einsum('ab,bc->ac',X,Y))
Out[91]: True
In [92]: (X@Y)[3,9]
Out[92]: 0.0
# Write the data
fp = open("_L_", "w")
fp.write(L)
fp.close()
fp = open("_Linv_", "w")
fp.write(Linv)
fp.close()
# Load them as numpy array
L = np.loadtxt("_L_")
Linv = np.loadtxt("_Linv_")
L = np.genfromtxt(L.splitlines(), dtype = np.float128)
Linv = np.genfromtxt(Linv.splitlines(), dtype = np.float128)