我正在运行代码以生成B中位置的掩码,该掩码距离A的某个距离D更近。
N = [[0 for j in range(length_B)] for i in range(length_A)]
dSquared = D*D
for i in range(length_A):
for j in range(length_B):
if ((A[j][0]-B[i][0])**2 + (A[j][1]-B[i][1])**2) <= dSquared:
N[i][j] = 1
对于长达数万个位置的A和B列表,此代码需要一段时间。我非常确定有一种方法可以对其进行矢量化,以使其运行得更快。谢谢。
答案 0 :(得分:3)
使用2d数组索引可视化此代码更容易:
for j in range(length_A):
for i in range(length_B):
dist = (A[j,0] - B[i,0])**2 + (A[j,1] - B[i,1])**2
if dist <= dSquared:
N[i, j] = 1
dist
表达式看起来像
((A[j,:] - B[i,:])**2).sum(axis=1)
使用2个元素,这个数组表达式可能不会更快,但它应该有助于我们重新思考这个问题。
我们可以执行广播的i,j
,outter
问题
A[:,None,:] - B[None,:,:] # 3d difference array
dist=((A[:,None,:] - B[None,:,:])**2).sum(axis=-1) # (lengthA,lengthB) array
将此与dSquared
进行比较,并使用生成的布尔数组作为掩码,将N
的元素设置为1:
N = np.zeros((lengthA,lengthB))
N[dist <= dSquared] = 1
我没有测试过这段代码,所以可能存在错误,但我认为基本的想法是存在的。并且可能已经足够让您了解其他案例的细节。
答案 1 :(得分:2)
你可以使用scipy's cdist
对于这样的距离计算非常有效,如此 -
from scipy.spatial.distance import cdist
N = (cdist(A,B,'sqeuclidean') <= dSquared).astype(int)
根据@hpaulj's solution
的建议,也可以使用broadcasting
。现在,根据问题中的已发布代码,我们看起来正在处理Nx2
形状的数组。因此,我们基本上可以对第一列和第二列进行切片,并分别对它们进行广播减法。好处是我们不会去3D
并因此保持内存效率,这也可能转化为性能提升。因此,平方的欧氏距离将如此计算 -
sq_eucl_dist = (A[:,None,0] - B[:,0])**2 + (A[:,None,1] - B[:,1])**2
让所有这三种方法用于平方欧氏距离计算。
运行时测试 -
In [75]: # Input arrays
...: A = np.random.rand(200,2)
...: B = np.random.rand(200,2)
...:
In [76]: %timeit ((A[:,None,:] - B[None,:,:])**2).sum(axis=-1) # @hpaulj's solution
1000 loops, best of 3: 1.9 ms per loop
In [77]: %timeit (A[:,None,0] - B[:,0])**2 + (A[:,None,1] - B[:,1])**2
1000 loops, best of 3: 401 µs per loop
In [78]: %timeit cdist(A,B,'sqeuclidean')
1000 loops, best of 3: 249 µs per loop
答案 2 :(得分:0)
我接下来建议使用上面的Numpy。循环代码也比A需要更多地索引到A中。你可以使用类似的东西:
import numpy as np
dimension = 10000
A = np.random.rand(dimension, 2) + 0.0
B = np.random.rand(dimension, 2) + 1.0
N = []
d = 1.0
for i in range(len(A)):
distances = np.linalg.norm(B - A[i,:], axis=1)
for j in range(len(distances)):
if distances[j] <= d:
N.append((i,j))
print(len(N))
用纯粹的Python来获得这样的性能会非常困难。我还要指出,更维度的数组解决方案需要很多内存。
答案 3 :(得分:0)
如果您的矩阵N可能很稀疏,scipy.spatial.cKDTree将比基于计算所有距离暴力的任何方法提供更好的时间复杂度:
cKDTree(A).sparse_distance_matrix(cKDTree(B), max_distance=D)