将每列的点积与自身相乘并存储在新的数组维度中

Take the dot product for each column with itself and store in new array dimension

我需要在给定的二维数组中对每一列的点积进行自身的转置。目前,我正在使用循环,它又慢又难看,所以我想知道如何用纯数组操作(如果可能的话)来做到这一点,例如使用 einsum 和类似工具。

MWE:

import numpy as np
A = np.random.randint(2,15,size=(2,3))

>>>A
array([[14,  9,  4],
       [12,  8,  2]])

这是我想要的,包括我目前的做法:

AA = [A[:,i].reshape(-1,1).dot(A[:,i].reshape(-1,1).T) for i in range(3)]
>>>AA
[array([[196, 168],
        [168, 144]]),
 array([[81, 72],
        [72, 64]]),
 array([[16,  8],
        [ 8,  4]])]

最后

>>>np.stack(AA,axis=0)
array([[[196, 168],
        [168, 144]],

       [[ 81,  72],
        [ 72,  64]],

       [[ 16,   8],
        [  8,   4]]])

形状为 (3,2,2).

现在显然在我的实际问题中,A 很大,因此当前的方法不可行。那么如何才能做得更好呢?

您可以使用 numpy.einsum:

import numpy as np
A = np.array([
       [14,  9,  4],
       [12,  8,  2]
    ])

np.einsum('ik,jk->kij', A, A)
array([[[196, 168],
        [168, 144]],

       [[ 81,  72],
        [ 72,  64]],

       [[ 16,   8],
        [  8,   4]]])

这实际上是一种外积,而不是dot。没有产品总和 - 除了您使用重塑创建的新尺寸 1 尺寸。

In [351]: A = np.array([
     ...:        [14,  9,  4],
     ...:        [12,  8,  2]
     ...:     ])

与共同播出的“外”品:

In [352]: A[:,None,:]*A[None,:,:]
Out[352]: 
array([[[196,  81,  16],
        [168,  72,   8]],

       [[168,  72,   8],
        [144,  64,   4]]])
In [353]: _.shape
Out[353]: (2, 2, 3)

这些是所需的数字,但最后是“3”形状,如 A。我们可以转置它。或者先转置A

In [354]: A.T[:,None,:]*A.T[:,:,None]
Out[354]: 
array([[[196, 168],
        [168, 144]],

       [[ 81,  72],
        [ 72,  64]],

       [[ 16,   8],
        [  8,   4]]])