2d 与 3d 之间的矩阵乘法?
Matrix multiplication between 2d with 3d?
这是两个矩阵:
a的形状是(2, 2),b的形状是(2, 2, 3)
我想得到形状为 (2, 3)
的 c
如何使用 a 和 b 得到 c?
a = array([[0.5, 0.5],
[0.6, 0.4]])
b = array([[[1, 2, 1],
[1, 3, 1]],
[[2, 1, 2],
[3, 1, 3]]])
c = array([[1. , 2.5, 1. ],
[2.4 , 1.2, 2.4 ]])
# c = [[0.5*1+0.5*1, 0.5*2+0.5*3, 0.5*1+0.5*1],
[0.6*2+0.4*3, 0.6*1+0.4*1, 0.6*2+0.4*3]]
# [0.5, 0.5] * [[1, 2, 1],
[1, 3, 1]]
# [0.6, 0.4] * [[2, 1, 2],
[3, 1, 3]]
使用 einsum
试试 np.einsum
(documentation). If you want to know more about how np.einsum
works, then check this 这分解了它的工作原理 -
np.einsum('ij,ijk->ik',a,b)
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
使用广播
上面的einsum
相当于下面的multiply->reduce->transpose
Note: a[:,:,None]
adds an additional axis to matrix a
such that (2,2) -> (2,2,1). This allows it to be broadcasted in operations with b
which is of the shape (2,2,3).
(a[:,:,None]*b).sum(1)
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
使用 Tensordot
查看 tensordot 文档 here
np.tensordot(a,b, axes=[1,1]).diagonal().T
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
相对较新的 matmul
旨在处理这样的 'batch' 操作。 3个维度中的第一个是batch维度,所以我们必须调整a
为3d。
In [156]: a = np.array([[0.5, 0.5],
...: [0.6, 0.4]])
...:
...: b = np.array([[[1, 2, 1],
...: [1, 3, 1]],
...:
...: [[2, 1, 2],
...: [3, 1, 3]]])
In [157]: (a[:,None]@b)[:,0]
Out[157]:
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
用 einsum 术语来说就是
np.einsum('ilj,ijk->ik',a[:,None],b)
添加了 l
维度(稍后从结果中删除)
这是两个矩阵:
a的形状是(2, 2),b的形状是(2, 2, 3)
我想得到形状为 (2, 3)
如何使用 a 和 b 得到 c?
a = array([[0.5, 0.5],
[0.6, 0.4]])
b = array([[[1, 2, 1],
[1, 3, 1]],
[[2, 1, 2],
[3, 1, 3]]])
c = array([[1. , 2.5, 1. ],
[2.4 , 1.2, 2.4 ]])
# c = [[0.5*1+0.5*1, 0.5*2+0.5*3, 0.5*1+0.5*1],
[0.6*2+0.4*3, 0.6*1+0.4*1, 0.6*2+0.4*3]]
# [0.5, 0.5] * [[1, 2, 1],
[1, 3, 1]]
# [0.6, 0.4] * [[2, 1, 2],
[3, 1, 3]]
使用 einsum
试试 np.einsum
(documentation). If you want to know more about how np.einsum
works, then check this
np.einsum('ij,ijk->ik',a,b)
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
使用广播
上面的einsum
相当于下面的multiply->reduce->transpose
Note:
a[:,:,None]
adds an additional axis to matrixa
such that (2,2) -> (2,2,1). This allows it to be broadcasted in operations withb
which is of the shape (2,2,3).
(a[:,:,None]*b).sum(1)
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
使用 Tensordot
查看 tensordot 文档 here
np.tensordot(a,b, axes=[1,1]).diagonal().T
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
相对较新的 matmul
旨在处理这样的 'batch' 操作。 3个维度中的第一个是batch维度,所以我们必须调整a
为3d。
In [156]: a = np.array([[0.5, 0.5],
...: [0.6, 0.4]])
...:
...: b = np.array([[[1, 2, 1],
...: [1, 3, 1]],
...:
...: [[2, 1, 2],
...: [3, 1, 3]]])
In [157]: (a[:,None]@b)[:,0]
Out[157]:
array([[1. , 2.5, 1. ],
[2.4, 1. , 2.4]])
用 einsum 术语来说就是
np.einsum('ilj,ijk->ik',a[:,None],b)
添加了 l
维度(稍后从结果中删除)