我最近转到Python 3.5,注意到新的矩阵乘法运算符(@)有时与numpy dot运算符的行为不同。例如,对于3d数组:
import numpy as np
a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b # Python 3.5+
d = np.dot(a, b)
@
运算符返回一个形状数组:
c.shape
(8, 13, 13)
而np.dot()
函数返回:
d.shape
(8, 13, 8, 13)
我如何用numpy dot重现相同的结果?是否有其他显著差异?
6条答案
按热度按时间zzwlnbp81#
@
运算符调用数组的__matmul__
方法,而不是dot
。该方法也作为函数np.matmul
出现在API中。来自文档:
matmul
与dot
有两个重要的区别。最后一点清楚地表明,
dot
和matmul
方法在传递3D(或更高维)数组时的行为不同。引用文档中的一些内容:对于
matmul
:如果任一参数是N-D,N〉2,则将其视为驻留在最后两个索引中的矩阵的堆栈并相应地广播。
对于
np.dot
:对于2-D数组,它等价于矩阵乘法,对于1-D数组,它等价于向量的内积(没有复共轭)。* 对于N维,它是a的最后一个轴和b的倒数第二个轴的和积 *
llew8vvj2#
仅供参考,
@
和它的numpy等价物dot
和matmul
都同样快(用perfplot创建的图,我的一个项目)。用于重现绘图的代码:
7tofc5zh3#
@ajcr的回答解释了
dot
和matmul
(由@
符号调用)的不同之处。通过查看一个简单的示例,可以清楚地看到两者在操作“矩阵堆栈”或Tensor时的不同行为。为了阐明差异,取一个4x 4数组,并返回
dot
乘积和matmul
乘积以及3x 4x 2“矩阵堆栈”或Tensor。每个操作的乘积显示在下面。请注意点积是怎样的,
a的最后一个轴与b的倒数第二个轴的和积
以及如何通过一起广播矩阵来形成矩阵乘积。
rqdpfwrv4#
在数学上,我认为numpy中的点更有意义
dot(a,B)_{i,j,k,a,b,c} =
因为当a和B是向量时它给出点积,或者当a和b是矩阵时它给出矩阵乘法
至于numpy中的matmul操作,它由dotresult的部分组成,可以定义为
matmul(a,B)_{i,j,k,c} =
所以,你可以看到**matmul(a,B)**返回一个小形状的数组,它的内存消耗更小,在应用中更有意义。特别是,结合broadcasting,你可以得到
(a,B)_{i,j,k,l} =
例如。
从上面的两个定义可以看出使用这两个操作的要求,假设a.shape=(s1,s2,s3,s4)和b.shape=(t1,t2,t3,t4)
1.t3=s4;
1.t2=s2,或t2和s2之一为1
1.t1=s1,或t1和s1之一为1
使用下面的代码来说服自己。
j2qf4p5b5#
下面是与
np.einsum
的比较,以显示索引是如何投影的i2byvkas6#
我的经验与MATMUL和DOT
我经常收到“ValueError:当尝试使用MATMUL时,传递值的形状是(200,1),索引意味着(200,3)”。我想要一个快速的解决方案,并发现DOT提供了相同的功能。我使用DOT没有得到任何错误。我得到了正确的答案
关于MATMUL
关于DOT