当矩阵a是二维、矩阵b是三维时,如何理解matmul函数?

问题描述 投票:0回答:2
a=np.arange(8).reshape(2,2,2)
b=np.arange(4).reshape(2,2)
print(np.matmul(a,b))

结果是:

[[[ 2  3]
  [ 6 11]]

 [[10 19]
  [14 27]]]

我不明白这个结果,有人可以解释一下吗?

python numpy
2个回答
3
投票

简短回答:它将第二个 2d 矩阵“广播”到 3d 矩阵,然后执行“映射”,因此它将元素子矩阵映射到结果中的新子矩阵。

正如np.matmul

[numpy-doc]
上的文档所说:

numpy.matmul(a, b, out=None)

两个数组的矩阵乘积。

行为取决于以下方式的参数。

  1. 如果两个参数都是二维的,它们会像传统矩阵一样相乘。
  2. 如果任一参数是 N 维,N > 2,则将其视为驻留在最后两个索引中的矩阵堆栈并广播 相应地。
  3. 如果第一个参数是一维的,则通过在其维度前添加 1 将其提升为矩阵。矩阵相乘后 删除前面的 1。
  4. 如果第二个参数是一维的,则通过在其维度上附加 1 将其提升为矩阵。矩阵相乘后 删除附加 1。

所以这里第二条适用。所以首先第二个矩阵也被“广播”到 3d 变体,这意味着我们乘以:

array([[[0, 1],
        [2, 3]],

       [[4, 5],
        [6, 7]]])

与:

array([[[0, 1],
        [2, 3]],

       [[0, 1],
        [2, 3]]])

我们将它们视为堆叠矩阵。所以首先我们乘以:

array([[0, 1],      array([[0, 1],
       [2, 3]])  x        [2, 3]])

这给了我们:

array([[ 2,  3],
       [ 6, 11]])

然后是元素第二个子矩阵:

array([[4, 5],      array([[0, 1],
       [6, 7]])  x        [2, 3]])

这给了我们:

array([[10, 19],
       [14, 27]])

因此,我们将它们叠加到结果中,并得到:

>>> np.matmul(a, b)
array([[[ 2,  3],
        [ 6, 11]],

       [[10, 19],
        [14, 27]]])

尽管行为已被完美定义,但最好谨慎使用此功能,因为对于 3d 矩阵与 2d 矩阵的“矩阵乘积”可能是什么样子,还有其他“有意义的”定义,因此不使用这些定义在这里。


1
投票

您可以更明确地将乘法视为求和。因此,如果

a
的尺寸为
(i, j, k)
并且
b
的尺寸为
(k, l)
,那么结果的尺寸将为
(i, j, l)

enter image description here

在代码中可以这样写(非常明确):

def matmul(a, b):
  dim1, dim2, dim3 = a.shape
  dim4 = b.shape[1]
  c = np.zeros(shape=(dim1, dim2, dim4))
  for i in range(dim1):
    for j in range(dim2):
      for l in range(dim4):
        c[i, j, l] = sum(a[i, j, k] * b[k, l] for k in range(dim3))
  return c

如果您尝试打印此

matmul()
函数的结果,它将与 numpy 函数相同。

注意:这个函数效率非常低,而且只有当a有3维而b有2维时才有效,但它可以很容易地推广。

© www.soinside.com 2019 - 2024. All rights reserved.