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'
假设我有一个 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'