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]] 如何理解结果?怎么来的
答案 0 :(得分:1)
简短答案:它将第二个2d矩阵“广播”到3d矩阵,然后执行“映射”,因此,它将元素级子矩阵映射到结果中的新子矩阵。
正如documentation on np.matmul
[numpy-doc]所说:
numpy.matmul(a, b, out=None)
两个数组的矩阵乘积。
行为通过以下方式取决于参数。
- 如果两个参数都是二维的,它们将像常规矩阵一样相乘。
- 如果任意一个参数均为N-D,N> 2 ,则将其视为驻留在最后两个索引中的矩阵堆栈,并进行广播 相应地。
- 如果第一个参数是1-D,则通过在其尺寸前面加1来将其提升为矩阵。矩阵相乘后 前面的1被删除。
- 如果第二个自变量是1-D,则通过在其尺寸后附加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]]])
尽管这样可以完美地定义行为,但是最好谨慎使用此功能,因为对于具有2d矩阵的3d矩阵,“矩阵乘积”的外观还有其他“感性”定义,因此在这里不使用。
答案 1 :(得分:1)
您可以更明确地将乘法视为求和。因此,如果a
的尺寸为(i, j, k)
,而b
的尺寸为(k, l)
,则结果的尺寸将为(i, j, l)
。
在代码中,可以这样写(非常明确):
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个维时才可以使用,但是可以很容易地将其推广。