Python:对矩阵的每一行单独取一个外积,取和返回一个和向量

Python: Taking a the outer product of each row of matrix by itself, taking the sum then returning a vector of sums

假设我有一个 N 乘 M 的矩阵 A。

我希望 return 一个 N 维向量 V,其中第 n 个元素是 A 的第 n 行中条目的所有成对乘积的双和。

在循环中,我想我可以这样做:

V = np.zeros(A.shape[0])
for n in range(A.shape[0]):
    for i in range(A.shape[1]):
        for j in range(A.shape[1]):
            V[n] += A[n,i] * A[n,j]

我想对此进行矢量化,我想我可以做到:

V_temp = np.einsum('ij,ik->ijk', A, A)
V = np.einsum('ijk->i', A)

但我认为这不是非常有效的内存方式,因为中间步骤 V_temp 不必要地存储整个外部产品,而我只需要求和。有更好的方法吗?

谢谢

您可以使用

V=np.einsum("ni,nj->n",A,A)

也许你可以使用

np.einsum('ij,ik->i', A, A)

或等价物

np.einsum(A, [0,1], A, [0,2], [0])

在 2015 年的 Macbook 上,我得到

In [35]: A = np.random.rand(100,100)

In [37]: %timeit for_loops(A)
640 ms ± 24.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [38]: %timeit np.einsum('ij,ik->i', A, A)
658 µs ± 7.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [39]: %timeit np.einsum(A, [0,1], A, [0,2], [0])
672 µs ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

你其实是在计算

A.sum(-1)**2

换句话说,外积之和就是因子之和的乘积。

演示:

A = np.random.random((1000,1000))
np.allclose(np.einsum('ij,ik->i', A, A), A.sum(-1)**2)
# True
t = timeit.timeit('np.einsum("ij,ik->i",A,A)', globals=dict(A=A,np=np), number=10)*100; f"{t:8.4f} ms"
# '948.4210 ms'
t = timeit.timeit('A.sum(-1)**2', globals=dict(A=A,np=np), number=10)*100; f"{t:8.4f} ms"
# '  0.7396 ms'