简体   繁体   English

Numpy einsum 沿轴计算外积

[英]Numpy einsum compute outer product along axis

I have two numpy arrays that contain compatible matrices and want to compute the element wise outer product of using numpy.einsum .我有两个 numpy arrays 包含兼容矩阵,并且想要计算使用numpy.einsum的元素明智外积。 The shapes of the arrays would be: arrays 的形状为:

A1 = (i,j,k)
A2 = (i,k,j) 

Therefore the arrays contain i matrices of shape (k,j) and (j,k) respectively.因此 arrays 分别包含i个形状为(k,j)(j,k)的矩阵。

So given A1 would contain the matrices A,B,C and A2 would contain matrices D,E,F , the result would be:所以假设A1将包含矩阵A,B,C并且A2将包含矩阵D,E,F ,结果将是:

A3 = (A(x)D,B(x)E,C(x)F)

With (x) being the outer product operator. (x)是外积算子。

This would yield to my understanding based on this answer an array A3 of the following shape:根据这个答案,这将产生我对以下形状的数组A3的理解:

A3 = (i,j*k,j*k)

So far I have tried:到目前为止,我已经尝试过:

np.einsum("ijk, ilm -> ijklm", A1, A2)

But the resulting shapes do not fit correctly.但生成的形状不正确。

As a sanity check I am testing for this:作为健全性检查,我正在对此进行测试:

A = np.asarray(([1,2],[3,4]))
B = np.asarray(([5,6],[7,8]))

AB_outer = np.outer(A,B)

A_vec = np.asarray((A,A))
B_vec = np.asarray((B,B))

# this line is not correct
AB_vec = np.einsum("ijk, ilm -> ijklm", A_vec,B_vec)

np.testing.assert_array_equal(AB_outer, AB_vec[0])

This currently throws an assertion error as my einsum notation is not correct.这当前会引发断言错误,因为我的 einsum 表示法不正确。 I am also open to any suggestions that can solve this and are faster or equally fast as nymphs einsum.我也愿意接受任何可以解决这个问题的建议,并且比若虫 einsum 更快或同样快。

We can extend dims and let broadcasting do the job for us -我们可以扩展 dims 并让broadcasting为我们完成这项工作 -

(A1[:,:,None,:,None]*A2[:,None,:,None,:]).swapaxes(2,3)

Sample run -样品运行 -

In [46]: A1 = np.random.rand(3,4,4)
    ...: A2 = np.random.rand(3,4,4)

In [47]: out = (A1[:,:,None,:,None]*A2[:,None,:,None,:]).swapaxes(2,3)

In [48]: np.allclose(np.multiply.outer(A1[0],A2[0]), out[0])
Out[48]: True

In [49]: np.allclose(np.multiply.outer(A1[1],A2[1]), out[1])
Out[49]: True

In [50]: np.allclose(np.multiply.outer(A1[2],A2[2]), out[2])
Out[50]: True

The equivalent with np.einsum would be - np.einsum的等价物是 -

np.einsum('ijk,ilm->ijklm',A1,A2)

You can compute the result running:您可以计算运行结果:

result = np.einsum('ijk,ikl->ijl', A1, A2)

I checked the above code on the following test data:我在以下测试数据上检查了上面的代码:

A = np.arange(1, 13).reshape(3, -1)
B = np.arange(2, 14).reshape(3, -1)
C = np.arange(3, 15).reshape(3, -1)
D = np.arange(1, 13).reshape(4, -1)
E = np.arange(2, 14).reshape(4, -1)
F = np.arange(3, 15).reshape(4, -1)
A1 = np.array([A, B, C])
A2 = np.array([D, E, F])

The result is:结果是:

array([[[ 70,  80,  90],
        [158, 184, 210],
        [246, 288, 330]],

       [[106, 120, 134],
        [210, 240, 270],
        [314, 360, 406]],

       [[150, 168, 186],
        [270, 304, 338],
        [390, 440, 490]]])

Now compute 3 "partial results":现在计算 3 个“部分结果”:

res_1 = A @ D
res_2 = B @ E
res_3 = C @ F

and check that they are just the same as consecutive sections of the result.并检查它们是否与结果的连续部分相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM