让我们说,我有一堆矩阵As和向量bs。
As = array([[[1, 7], [3, 8]],
[[2, 1], [5, 9]],
[[7, 2], [8, 3]]])
bs = array([[8, 0], [8, 8], [7, 3]])
当我做np.inner(As,bs)时,我得到:
array([[[ 8, 64, 28], [ 24, 88, 45]],
[[ 16, 24, 17], [ 40, 112, 62]],
[[ 56, 72, 55], [ 64, 88, 65]]])
但我不需要所有的内在产品。我想要的是,用每个向量计算一次矩阵。 我可以这样做:
np.array(map(lambda (a, b): np.inner(a, b), zip(As, bs)))
然后我得到了预期的矩阵:
array([[ 8, 24], [ 24, 112], [ 55, 65]])
现在我不想使用zip,map等因为我需要这个操作> 10 ** 6次(用于图像处理,完全用于GMM)。 有没有办法使用numpy,scipy等可以为我做这个? (快速而有效)
答案 0 :(得分:3)
您可以使用np.einsum
-
np.einsum('ijk,ik->ij',As, bs)
<强>解释强>
使用np.array(map(lambda (a, b): np.inner(a, b), zip(As, bs)))
,我们选择As
关闭的第一个元素为a
,关闭bs
为b
并执行内部产品。因此,我们正在做:
In [19]: np.inner(As[0],bs[0])
Out[19]: array([ 8, 24])
In [20]: np.inner(As[1],bs[1])
Out[20]: array([ 24, 112])
In [21]: np.inner(As[2],bs[2])
Out[21]: array([55, 65])
将其视为一个循环,我们迭代3次,对应于As
的第一轴的长度,这与bs
相同。因此,查看lambda
表达式,在每次迭代时,我们都有a = As[0] & b = bs[0]
,a = As[1] & b = bs[1]
等等。
As
和bs
为3D
和2D
,让我们将它们表示为想象我们思想中的内在产品的迭代器。因此,在迭代时,我们将a : j,k
和b : m
。使用a
和b
之间的内部产品,我们将丢失a
的第二个轴和b
的第一个轴。因此,我们需要将k
与m
对齐。因此,我们可以假设b
具有与k
相同的迭代器。从a
返回到As
和b
再到bs
,实质上我们会从As
丢失第三个轴,从bs
丢失第二个轴与内在产品/总和减少。沿着As
和bs
的第一个轴进行迭代表示我们需要在这些总和减少下保持这些对齐。
让我们总结一下。
我们有输入数组的迭代器,如此 -
As : i x j x k
bs : i x k
预期操作涉及的步骤:
As
的第一个轴与bs
的第一个轴对齐。As
的第三个轴,减去总和 - bs
的第二个。因此,我们将留下输出的迭代器i,j
。
np.einsum
是一种非常有效的实现,当我们需要保持输入数组的一个或多个轴彼此对齐时,它非常方便。
有关einsum
的更多信息,我建议您按照之前提供的文档链接进行操作,this Q&A
也可以提供帮助!