如何在Python中将每一对的矩阵向量内积分开?

PiM*_*age 5 python numpy vector matrix

可以说,我有一堆矩阵 As 和向量 bs 。

As = array([[[1, 7], [3, 8]],
            [[2, 1], [5, 9]],
            [[7, 2], [8, 3]]])
bs = array([[8, 0], [8, 8], [7, 3]])
Run Code Online (Sandbox Code Playgroud)

当我执行 np.inner(As, bs) 时,我得到:

array([[[  8,  64,  28], [ 24,  88,  45]],
       [[ 16,  24,  17], [ 40, 112,  62]],
       [[ 56,  72,  55], [ 64,  88,  65]]])
Run Code Online (Sandbox Code Playgroud)

但我不需要所有的内部产品。我想要的是,用每个向量计算每个矩阵一次。我可以做这样的事情:

np.array(map(lambda (a, b): np.inner(a, b), zip(As, bs)))
Run Code Online (Sandbox Code Playgroud)

然后我得到预期的矩阵:

array([[  8,  24], [ 24, 112], [ 55,  65]])
Run Code Online (Sandbox Code Playgroud)

现在我不想使用 zip、ma​​p 等,因为我需要此操作 > 10**6 次(对于图像处理,对于 GMM 来说)。有什么方法可以使用 numpy、scipy 等来为我做到这一点吗?(快速高效)

Div*_*kar 4

您可以使用np.einsum-

np.einsum('ijk,ik->ij',As, bs)
Run Code Online (Sandbox Code Playgroud)

解释

对于np.array(map(lambda (a, b): np.inner(a, b), zip(As, bs))),我们选择第一个元素 off Asasa和 off bsasb并进行内积。因此,我们正在做:

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])
Run Code Online (Sandbox Code Playgroud)

将其视为一个循环,我们迭代 3 次,对应于 的第一个轴的长度As,与 的相同bs。因此,看着lambda,在每次迭代中,我们有a = As[0] & b = bs[0]a = As[1] & b = bs[1]等等。

As和,让我们将它们表示为迭代器bs,想象我们脑海中的内积。因此,在迭代时,我们将得到和。通过和之间的内积,我们将失去 的第二个轴和 的第一个轴。因此,我们需要与保持一致。因此,我们可以假设具有与 相同的迭代器。回顾 from to和to ,本质上,我们将失去第三个轴 from和第二个轴 from以及内积/求和减少。沿着第一个轴迭代3D2Da : j,kb : mababkmbkaAsbbsAsbsAsbs意味着我们需要在这些总和减少下保持这些对齐。

我们来总结一下。

我们有涉及输入数组的迭代器,如下所示 -

As :  i x j x k 
bs :  i x k
Run Code Online (Sandbox Code Playgroud)

预期操作涉及的步骤:

  • 保持第一个轴As与第一个轴对齐bs
  • 失去 的第三个轴,As并与 的第二个轴进行求和bs

因此,我们将剩下迭代器i,j输出的迭代器。

np.einsum是一种非常有效的实现,当我们需要保持输入数组的一个或多个轴彼此对齐时,它特别方便。

有关 的更多信息einsum,我建议您按照之前提供的文档链接进行操作,这也this Q&A可能会有所帮助!