计算numpy数组之间的距离

时间:2016-12-06 13:50:38

标签: python performance numpy

我有两个数组,第一个np.array是来自的点,第二个np.array是我需要计算的所有距离。

示例:

 import numpy as np
 from_array = np.array([(0,1), (1,1), ..., (x,y)])
 to_array = np.array([(5,1), (3,1), ..., (x,y)])

我需要做的是取from_array的第一个条目并计算from_array[0]到to_array中所有点之间的所有距离,然后保持最大距离。

所以我可以为此做好准备:

 def get_distances(from_array, to_array):
     results = []
     distances = []
     for pt in from_array:
        for to in to_array:
            results.append(calc_dist(pt, to))
        distances.append(results)
     return distances

但这很慢,我正在寻找一种优化的计算方法,因为我可以获得数千点。

最终目标是计算Hausdorff距离。

fhd = np.mean(np.min(SomeDistanceArray,axis=0))
rhd = np.mean(np.min(SomeDistanceArray,axis=1))
print (max(fhd, rhd))

我想使用numpy执行此任务。 我的距离可以是欧几里德或欧氏距离。

所以我正在寻求帮助的是一种优化的方法,用于计算两个np阵列的欧氏距离方法。应该注意的是,数组1可能比数组2有更多的行。意味着2D数组(x,y)的长度可以比​​较10行到30行。

2 个答案:

答案 0 :(得分:4)

这是一个基于NumPy的方法np.einsum -

subs = from_array[:,None] - to_array
sq_eucliean_dist = np.einsum('ijk,ijk->ij',subs,subs)
eucliean_dist = np.sqrt(sq_eucliean_dist)

注意:如果您稍后计算np.mean(np.min(SomeDistanceArray,axis=0)),则可以跳过eucliean_dist的计算并直接使用sq_eucliean_dist作为SomeDistanceArray,因为计算平方根会非常昂贵。

np.einsum('ijk,ijk->ij',subs,subs)做了什么?它在同一个数组subs之间执行元素乘法,即基本上是平方,然后沿最后一个轴进行求和,从而丢失它在那个减少过程中。

那么,为什么不明确地进行平方和求和呢?嗯,np.einsum的好处是它一步完成平方和求和,给我们显着的性能效率。

因此,最后如果from_array(N x 2)数组而to_array(M x 2)数组,则np.einsum的输出将是欧氏距离的平方作为2D形状数组(N x M)。 关于字符串表示法本身的更多信息将涉及更长时间的讨论,其中一些可以在this post和之前发布的官方文档链接中找到。

答案 1 :(得分:1)

仅限Numpy。所以没有scipy.spatial.distance.cdist

首先,不要使用元组,使用2xN和2xM阵列。然后广播。

np.linalg.norm(from_array[:,:,None]-to_array[:,None,:], axis=0)

如果你有一个古老版本的numpy而没有一个可升级的linalg.norm(即你正在使用Abaqus),请执行以下操作:

np.sum((from_array[:,:,None]-to_array[:,None,:])**2, axis=0).__pow__(0.5)
相关问题