numpy 矩阵的向量化乘法
numpy Vectorized multiplication of matrices
所以我想做的是这个...
假设我们有一组矩阵:
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
我将这些数组的集合矢量化以生成
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
然后我需要执行类似
的操作
A.T @ B @ C
我想以
的形式得到结果
np.array([A1.T @ B1 @ C1, A2.T @ B2 @ C2, A3.T @ B3 @ C3])
这些三元组矩阵的实际数量是数十万,所以我想使用 numpy 向量化来实现,例如某种形式的张量乘法
我已经尝试应用 np.tensordot,但它没有按预期正常工作:
np.tensordot(A, B, axes=((1), (1)))
产生:
array([[**[13, 16]**,
[26, 32],
[29, 35]],
[[26, 32],
**[52, 64]**,
[58, 70]],
[[34, 42],
[68, 84],
**[76, 92]**]])
而我希望它只是那些标记数组的数组(每个对应于 Ai.T @ Bi)
简单的 A @ B 产生相同的结果...
那么有没有一种方法可以产生预期的结果而无需在第一毛钱上循环
您好,您可以矢量化您的问题,添加一些维度并进行乘积:
import numpy as np
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
Res = (A[:,:,None]*B*C[:,None,:]).sum((1,2))
编辑
您也可以使用 Einsten 求和符号解决同样的问题(我刚刚意识到)。这样更直接也更容易。
res = np.einsum('ni,nij,nj->n',A,B,C)
形状:
In [272]: A.shape
Out[272]: (3, 2)
In [273]: B.shape
Out[273]: (3, 2, 2)
In [274]: C.shape
Out[274]: (3, 2)
子数组乘积是一个标量:
In [275]: (A1.T@B1@C1).shape
Out[275]: ()
In [276]: (A1.T@B1@C1)
Out[276]: 219
matmul/@
可以将第一个维度 (3) 视为一个批次,如果我们将所有数组扩展到 3d,请记住我们想要“A 的最后一个与第二个到最后一个 B " 规则最后 2 个维度:
In [277]: A[:,None,:]@B@C[:,:,None]
Out[277]:
array([[[ 219]],
[[1752]],
[[2704]]])
In [278]: _.shape
Out[278]: (3, 1, 1)
In [279]: (A[:,None,:]@B@C[:,:,None])[:,0,0]
Out[279]: array([ 219, 1752, 2704])
相当于einsum
是:
In [280]: np.einsum('ij,ijk,ik->i', A, B, C)
Out[280]: array([ 219, 1752, 2704])
这里batch
i
一路重复,而j
和k
就是大家熟悉的矩阵乘积变量
所以我想做的是这个...
假设我们有一组矩阵:
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
我将这些数组的集合矢量化以生成
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
然后我需要执行类似
的操作A.T @ B @ C
我想以
的形式得到结果np.array([A1.T @ B1 @ C1, A2.T @ B2 @ C2, A3.T @ B3 @ C3])
这些三元组矩阵的实际数量是数十万,所以我想使用 numpy 向量化来实现,例如某种形式的张量乘法
我已经尝试应用 np.tensordot,但它没有按预期正常工作:
np.tensordot(A, B, axes=((1), (1)))
产生:
array([[**[13, 16]**,
[26, 32],
[29, 35]],
[[26, 32],
**[52, 64]**,
[58, 70]],
[[34, 42],
[68, 84],
**[76, 92]**]])
而我希望它只是那些标记数组的数组(每个对应于 Ai.T @ Bi)
简单的 A @ B 产生相同的结果...
那么有没有一种方法可以产生预期的结果而无需在第一毛钱上循环
您好,您可以矢量化您的问题,添加一些维度并进行乘积:
import numpy as np
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
Res = (A[:,:,None]*B*C[:,None,:]).sum((1,2))
编辑
您也可以使用 Einsten 求和符号解决同样的问题(我刚刚意识到)。这样更直接也更容易。
res = np.einsum('ni,nij,nj->n',A,B,C)
形状:
In [272]: A.shape
Out[272]: (3, 2)
In [273]: B.shape
Out[273]: (3, 2, 2)
In [274]: C.shape
Out[274]: (3, 2)
子数组乘积是一个标量:
In [275]: (A1.T@B1@C1).shape
Out[275]: ()
In [276]: (A1.T@B1@C1)
Out[276]: 219
matmul/@
可以将第一个维度 (3) 视为一个批次,如果我们将所有数组扩展到 3d,请记住我们想要“A 的最后一个与第二个到最后一个 B " 规则最后 2 个维度:
In [277]: A[:,None,:]@B@C[:,:,None]
Out[277]:
array([[[ 219]],
[[1752]],
[[2704]]])
In [278]: _.shape
Out[278]: (3, 1, 1)
In [279]: (A[:,None,:]@B@C[:,:,None])[:,0,0]
Out[279]: array([ 219, 1752, 2704])
相当于einsum
是:
In [280]: np.einsum('ij,ijk,ik->i', A, B, C)
Out[280]: array([ 219, 1752, 2704])
这里batch
i
一路重复,而j
和k
就是大家熟悉的矩阵乘积变量