如何用广播计算点积?

时间:2018-02-07 18:47:06

标签: python numpy matrix numpy-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],
        [194]]])

但形状不是我想要的

c.shape
(2, 3, 1)
  1. 除了更改轴的方式外,如何在计算中得到形状(2, 3)而不是(2, 3, 1)

  2. 对于广播,为什么[:,None]不起作用? ...在这里意味着什么?

1 个答案:

答案 0 :(得分:2)

在这种情况下,b[...,None]b[:,:,None],(2,3,1)数组相同。 ...表示'尽可能多:'。

因此,点积和是3的{​​{1}}和a的中间3(第二个到最后一个)。

您可以使用b删除1号尺寸。

但是对于(2,3,3)和(2,3),您想要哪squeeze个产品?在dot表示法中,我可以看到

einsum
具有2个2d阵列的

'ijk,ij->ik' 'ijk,ik->ij' 'ijk,mj->imk' etc 产品定义明确。但是当一个人是3d时,就会产生一些歧义。

dot

来自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]]) 文档的相关说明是:

  

如果任一参数是N-D,则N> 2,它被视为一堆     驻留在最后两个索引中的矩阵并相应地进行广播。

     

ValueError - 如果matmul的最后一个维度与大小不同       a的倒数第二维。

b中广播的一个例子是:

matmul

更新

我刚刚了解到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]]]) 现在是optimize=True的默认值,而且这并不总是最快。

einsum

Einsum optimize fails for basic operation