在python中分别查找列表的每个元素的转置



我有一个包含N个项目的列表,每个项目都有d个维度(所以本质上是一个N x d列表(。对于每个项目,我想找到与自身转置的项目的乘积,因此,N 个项目中每个项目的 x.xT。这将给我一个 N x d x d 数组。我怎样才能在 numpy 中有效地做到这一点。此时,我正在遍历每个项目并分别找到转置。

for i in range(len(mu[0])):
current_mu = mu[i] # list of d elements
distances = []
for index in range(len(samples)):
distance = np.asarray(current_mu - samples[index])[:, None] # list of d elements
distances.append(distance * distance.T) # each becomes d x d

我可以删除第二个嵌套循环还是必需的?

你可以按如下方式使用 numpy.einsum:

import numpy as np
N,d = 10,5
mu = np.random.rand(N,d)
r = np.einsum('ni,nj->nij', mu, mu)
r.shape
(10,5,5)

与 for 循环实现相比:

def for_loop(a):
N,d = a.shape
r = np.zeros((N,d,d))
for i in range(N):
r[i] = a[i][:,None] @ a[i][None,:]
# N>d case
N,d = 1000,500
mu = np.random.rand(N,d)
%timeit np.einsum('ni,nj->nij', mu, mu)
1.29 s ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit for_loop(mu)
2.36 s ± 45.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# N<d case
N,d = 100,1000
mu = np.random.rand(N,d)
%timeit np.einsum('ni,nj->nij', mu, mu)
521 ms ± 9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit for_loop(mu)
976 ms ± 18.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

在这两种情况下,性能几乎是 2 倍。

@FBruzzesi前面的答案非常有效,但如果有人更喜欢不使用 einsum(以及一般的完整性(的解决方案:

n,d=1000,500
x=np.random.randn(n,d,1)
x_einsum=x.reshape(n,d)
%timeit x * x.transpose((0,2,1))
744 ms ± 48.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.einsum('ni,nj->nij', x_einsum, x_einsum)
777 ms ± 18.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

最新更新