Python 如何用广播计算点积?
我想计算点积Python 如何用广播计算点积?,python,numpy,matrix,array-broadcasting,dot-product,Python,Numpy,Matrix,Array Broadcasting,Dot Product,我想计算点积 a=np.arange(18).reshape(2,3,3) b=np.arange(6).reshape(2,3) 在广播方面,我试着 a[0]@b[0] array([ 5, 14, 23]) a[1]@b[1] array([122, 158, 194]) 但是形状不是我想要的 c=a@b[...,None] c array([[[ 5], [ 14], [ 23]], [[122], [158],
a=np.arange(18).reshape(2,3,3)
b=np.arange(6).reshape(2,3)
在广播方面,我试着
a[0]@b[0]
array([ 5, 14, 23])
a[1]@b[1]
array([122, 158, 194])
但是形状不是我想要的
c=a@b[...,None]
c
array([[[ 5],
[ 14],
[ 23]],
[[122],
[158],
[194]]])
(2,3)
,而不是(2,3,1)
,而不是改变轴的方式[:,None]
不起作用?这里的…
是什么意思在本例中,
b[…,None]
与b[:,:,None]
,a(2,3,1)数组相同…
表示“根据需要尽可能多的:
”
因此,点积和与a
的最后3
和b
的中间3
(倒数第二)
您可以使用挤压
来去除大小为1的维度
但是对于(2,3,3)和(2,3),您想要哪个dot
产品?在einsum
符号中,我可以看到
c.shape
(2, 3, 1)
dot
具有2个2d阵列的产品定义良好。但是当一个是3d的时候,会有一些模棱两可的地方
'ijk,ij->ik'
'ijk,ik->ij'
'ijk,mj->imk'
etc
matmul
文件中的相关注释如下:
如果任一参数为N-D,N>2,则将其视为
位于最后两个索引中的矩阵,并相应地广播
ValueError-如果a
的最后一个维度的大小与
b
的倒数第二个维度
matmul
中的广播示例如下:
In [2]: a=np.arange(18).reshape(2,3,3)
...: b=np.arange(6).reshape(2,3)
...:
In [3]: np.einsum('ijk,ik->ij',a,b)
Out[3]:
array([[ 5, 14, 23],
[122, 158, 194]])
In [4]: np.dot(a,b)
ValueError: shapes (2,3,3) and (2,3) not aligned: 3 (dim 2) != 2 (dim 0)
In [6]: np.dot(a,b[:,:,None]).shape # 'ijk,kml->ijml'
Out[6]: (2, 3, 2, 1)
In [7]: np.matmul(a,b[:,:,None]).shape # @
Out[7]: (2, 3, 1)
In [8]: np.einsum('ijk,ikm->ijm',a,b[...,None])
Out[8]:
array([[[ 5],
[ 14],
[ 23]],
[[122],
[158],
[194]]])
In [12]: np.squeeze(_) # removing that added dimension
Out[12]:
array([[ 5, 14, 23],
[122, 158, 194]])
更新
我刚刚了解到,optimize=True
现在是einsum
的默认值,而且这并不总是最快的
In [15]: a@b.T
Out[15]:
array([[[ 5, 14],
[ 14, 50],
[ 23, 86]],
[[ 32, 122],
[ 41, 158],
[ 50, 194]]])
In [16]: _.shape
Out[16]: (2, 3, 2)
In [17]: a@b.T[None,:,:]
Out[17]:
array([[[ 5, 14],
[ 14, 50],
[ 23, 86]],
[[ 32, 122],
[ 41, 158],
[ 50, 194]]])
在这种情况下,
b[…,None]
与b[:,:,None]
,a(2,3,1)数组相同…
表示“根据需要尽可能多的:
”
因此,点积和与a
的最后3
和b
的中间3
(倒数第二)
您可以使用挤压
来去除大小为1的维度
但是对于(2,3,3)和(2,3),您想要哪个dot
产品?在einsum
符号中,我可以看到
c.shape
(2, 3, 1)
dot
具有2个2d阵列的产品定义良好。但是当一个是3d的时候,会有一些模棱两可的地方
'ijk,ij->ik'
'ijk,ik->ij'
'ijk,mj->imk'
etc
matmul
文件中的相关注释如下:
如果任一参数为N-D,N>2,则将其视为
位于最后两个索引中的矩阵,并相应地广播
ValueError-如果a
的最后一个维度的大小与
b
的倒数第二个维度
matmul
中的广播示例如下:
In [2]: a=np.arange(18).reshape(2,3,3)
...: b=np.arange(6).reshape(2,3)
...:
In [3]: np.einsum('ijk,ik->ij',a,b)
Out[3]:
array([[ 5, 14, 23],
[122, 158, 194]])
In [4]: np.dot(a,b)
ValueError: shapes (2,3,3) and (2,3) not aligned: 3 (dim 2) != 2 (dim 0)
In [6]: np.dot(a,b[:,:,None]).shape # 'ijk,kml->ijml'
Out[6]: (2, 3, 2, 1)
In [7]: np.matmul(a,b[:,:,None]).shape # @
Out[7]: (2, 3, 1)
In [8]: np.einsum('ijk,ikm->ijm',a,b[...,None])
Out[8]:
array([[[ 5],
[ 14],
[ 23]],
[[122],
[158],
[194]]])
In [12]: np.squeeze(_) # removing that added dimension
Out[12]:
array([[ 5, 14, 23],
[122, 158, 194]])
更新
我刚刚了解到,optimize=True
现在是einsum
的默认值,而且这并不总是最快的
In [15]: a@b.T
Out[15]:
array([[[ 5, 14],
[ 14, 50],
[ 23, 86]],
[[ 32, 122],
[ 41, 158],
[ 50, 194]]])
In [16]: _.shape
Out[16]: (2, 3, 2)
In [17]: a@b.T[None,:,:]
Out[17]:
array([[[ 5, 14],
[ 14, 50],
[ 23, 86]],
[[ 32, 122],
[ 41, 158],
[ 50, 194]]])
Thx,我再次编辑我的问题,我想点积
a[0]@b[0]
和a[1]@b[1]
。我仍然可以使用@
操作符来实现形状(2,3)
?@kindchan,根据matmul
规则,您需要展开b
,使其为三维。a
的最后一个dim必须与b
的第二个到最后一个匹配。为了得到(2,3),你已经挤出了你添加的维度-after.thx对于所有事情,我认为np.einsum
可能是一个更好的方法。thx,我再次编辑我的问题,我想点积a[0]@b[0]
和a[1]@b[1]
。我仍然可以使用@
操作符来实现形状(2,3)
?@kindchan,根据matmul
规则,您需要展开b
,使其为三维。a
的最后一个dim必须与b
的第二个到最后一个匹配。为了得到(2,3),您已经挤出了您添加的维度-after.thx,我认为np.einsum
可能是一个更好的方法。您并不是真正的广播。在产品中使用b
之前,先展开其维度<代码>a@b.T确实使用广播,将b.T
扩展到(1,3,2)到(3,3,2),这点产生(2,3,2)。你不是真正的广播。在产品中使用b
之前,先展开其维度<代码>a@b.T
确实使用广播,将b.T
扩展到(1,3,2)到(3,3,2),从而点
产生(2,3,2)。