numpy 向量中的三个for循环

9fkzdhlc  于 2023-01-09  发布在  其他
关注(0)|答案(2)|浏览(111)

我有一个简单的numpy数组(3xN),如下所示:

v = np.array([[-3.33829, -3.42467, -3.53332],
   [-2.67681, -2.6082 , -3.49502],
   [-3.49497, -2.73177, -2.61499],
   [-2.76056, -3.57753, -2.67334],
   [-1.96801, -3.47521, -3.51974],
   [-1.25571, -2.69451, -3.45554],
   [-1.94568, -2.59504, -2.72568],
   [-1.28991, -3.47927, -2.73176],
   [-0.51201, -3.50684, -3.40448],
   [ 0.22398, -2.70244, -3.43421]])

这里,N = 10,但在我的真实的情况下,它比这里(+500)大得多,每一行都是一个点--欧几里得坐标。
我想执行:

其中i、j和k表示与v不同的行。
我怎样才能在Python上快速地实现它呢?

vsaztqbk

vsaztqbk1#

您可以使用numpy broadcasting操作来完成此操作:

diffs = ((v[:, None] - v) ** 2).sum(-1)
d = np.exp(diffs + diffs[:, None]).sum((0, 1))
print(d)

# [3.08316899e+11 2.37020625e+07 4.05357364e+12 8.22697743e+08
#  8.85209202e+04 2.55340202e+05 7.33879459e+04 1.88175133e+05
#  8.10134295e+08 6.62122925e+12]

即使对于大小为500的数组,计算结果也只需几秒钟:

%%time
v = np.random.rand(500, 3)
diffs = np.sum((v[:, None] - v) ** 2, -1)
d = np.exp(diffs + diffs[:, None]).sum((0, 1))

# CPU times: user 2.74 s, sys: 5.5 ms, total: 2.75 s
# Wall time: 2.75 s
oxiaedzo

oxiaedzo2#

IIUC,该方程表示成对向量差异,而不是向量之间的平方距离。

N个向量之间的成对差将是N * N个向量。
最后,我假设您只在jk轴上进行缩减,输出向量是(10,3)而不是(10,)

import numpy as np

d = np.exp(((v[:,None]-v)**2)[:,None] + ((v[:,None]-v)**2)).sum((0,1))
print(d)

#### Stepwise breakdown
#v                           #i,3 -> 10,3
#diff = (v[:,None]-v)**2     #j,i,3 -> 10,10,3
#power = diff[:,None]+diff   #k,j,i,3 -> 10,10,10,3
#exp = np.exp(power)         #k,j,i,3 -> 10,10,10,3
#d = np.sum(exp,(1,2))       #i,3 -> 10,3
array([[4.38558108e+11, 2.11224470e+02, 2.08153285e+02],
       [6.10332697e+09, 2.42309774e+02, 2.00079357e+02],
       [1.37237360e+12, 2.11552094e+02, 2.32739462e+02],
       [9.98934092e+09, 2.51158071e+02, 2.16562340e+02],
       [1.77827910e+08, 2.22151678e+02, 2.05163797e+02],
       [1.91234145e+08, 2.19457894e+02, 1.92858561e+02],
       [1.63391357e+08, 2.46419838e+02, 2.04498335e+02],
       [1.67512751e+08, 2.23119070e+02, 2.03232700e+02],
       [8.45322705e+09, 2.30065042e+02, 1.85024981e+02],
       [1.14468558e+12, 2.17683864e+02, 1.89388595e+02]])

基准-

%%timeit
np.exp(((v[:,None]-v)**2)[:,None] + ((v[:,None]-v)**2)).sum((0,1))
# 21.2 s ± 3.27 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

相关问题