Python 加速简单的距离计算
我正在实现一个简单的代码,它计算Python 加速简单的距离计算,python,performance,algorithm,numpy,distance,Python,Performance,Algorithm,Numpy,Distance,我正在实现一个简单的代码,它计算列表中的一个点(x\u a,y\u a)和列表中的所有点(x\u b,y\u b)之间的距离,并返回找到的最小距离。这将对列表中的所有点重复执行 我的代码的MWE: # list_A points defined in array. list_A = np.array([ [x_data_a, # x y_data_a] # y ], dtype=float) # list_B points defined in list. lis
列表中的一个点(x\u a,y\u a)
和列表中的所有点(x\u b,y\u b)
之间的距离,并返回找到的最小距离。这将对列表中的所有点重复执行
我的代码的MWE
:
# list_A points defined in array.
list_A = np.array([
[x_data_a, # x
y_data_a] # y
], dtype=float)
# list_B points defined in list.
list_B = [[x_data_b], [y_data_b]]
# Iterate through all data points in list_A
for ind, x_a in enumerate(list_A[0][0]):
y_a = list_A[0][1][ind]
# Iterate through all points in list_B.
dist_min = 1000.
for ind2, x_b in enumerate(list_B[0]):
y_b = list_B[1][ind2]
# Find distance between points.
dist = (x_a-x_b)**2 + (y_a-y_b)**2
if dist < dist_min:
# Update value of min distance.
dist_min = dist
print 'Min dist to (', x_a, y_a, '): ', dist_min
对于大型列表/数组,这可能需要相当长的时间才能完成。这可以加快速度吗?使用,您根本不需要编写自己的距离计算代码
编辑:您需要转换数据。其格式应如下所示:
list_A = [[[1.2 2.3 1.5 2.3 5.8 4.6 9.1] [2.5 1.0 4.6 2.4 7.4 1.1 3.2]]]
list_B = [[1.4, 5.8, 7.9], [6.1, 1.2, 3.7]]
list_A = [
[1, 2],
[3, 4],
[4, 5]
]
list_B = [
[8, 9],
[10, 11],
[11, 12],
[13, 14]
]
目前,您拥有的是一个X坐标列表和一个单独的Y坐标列表。您需要重新定向这些对象,以便有一个XY对列表。如果您的数据是普通列表,您可以使用list_A=zip(*list_A)
对其进行转换;如果它们是numpy数组,您可以使用list\u A=list\u A.T
对它们进行转置,而无需编写自己的距离计算代码
编辑:您需要转换数据。其格式应如下所示:
list_A = [[[1.2 2.3 1.5 2.3 5.8 4.6 9.1] [2.5 1.0 4.6 2.4 7.4 1.1 3.2]]]
list_B = [[1.4, 5.8, 7.9], [6.1, 1.2, 3.7]]
list_A = [
[1, 2],
[3, 4],
[4, 5]
]
list_B = [
[8, 9],
[10, 11],
[11, 12],
[13, 14]
]
目前,您拥有的是一个X坐标列表和一个单独的Y坐标列表。您需要重新定向这些对象,以便有一个XY对列表。如果您的数据是普通列表,您可以使用list_A=zip(*list_A)
对其进行转换;如果它们是numpy数组,您可以使用list\u A=list\u A.T
将它们转置,运行您的代码,我将获得以下结果:
Min dist to ( 1.2 2.5 ): 13.0
Min dist to ( 2.3 1.0 ): 12.29
Min dist to ( 1.5 4.6 ): 2.26
Min dist to ( 2.3 2.4 ): 13.69
Min dist to ( 5.8 7.4 ): 18.1
Min dist to ( 4.6 1.1 ): 1.45
Min dist to ( 9.1 3.2 ): 1.69
将阵列转换为以下Nx2阵列:
a
[[ 1.2 2.5]
[ 2.3 1. ]
[ 1.5 4.6]
[ 2.3 2.4]
[ 5.8 7.4]
[ 4.6 1.1]
[ 9.1 3.2]]
b
[[ 1.4 6.1]
[ 5.8 1.2]
[ 7.9 3.7]]
现在,以下几点应该可以发挥作用:
import scipy.spatial.distance as spdist
dist_arr = spdist.cdist(a,b)
print dist_arr**2
[[ 13. 22.85 46.33]
[ 26.82 12.29 38.65]
[ 2.26 30.05 41.77]
[ 14.5 13.69 33.05]
[ 21.05 38.44 18.1 ]
[ 35.24 1.45 17.65]
[ 67.7 14.89 1.69]]
ind = np.argmin(dist_arr,axis=1)
print ind
[0 1 0 1 2 1 2]
print dist_arr[np.arange(ind.shape[0]),ind]**2
[ 13. 12.29 2.26 13.69 18.1 1.45 1.69]
如果a
和b
为2X5000,而原始代码为135秒,则需要约.3秒。450倍的加速。运行您的代码,我可以获得以下结果:
Min dist to ( 1.2 2.5 ): 13.0
Min dist to ( 2.3 1.0 ): 12.29
Min dist to ( 1.5 4.6 ): 2.26
Min dist to ( 2.3 2.4 ): 13.69
Min dist to ( 5.8 7.4 ): 18.1
Min dist to ( 4.6 1.1 ): 1.45
Min dist to ( 9.1 3.2 ): 1.69
将阵列转换为以下Nx2阵列:
a
[[ 1.2 2.5]
[ 2.3 1. ]
[ 1.5 4.6]
[ 2.3 2.4]
[ 5.8 7.4]
[ 4.6 1.1]
[ 9.1 3.2]]
b
[[ 1.4 6.1]
[ 5.8 1.2]
[ 7.9 3.7]]
现在,以下几点应该可以发挥作用:
import scipy.spatial.distance as spdist
dist_arr = spdist.cdist(a,b)
print dist_arr**2
[[ 13. 22.85 46.33]
[ 26.82 12.29 38.65]
[ 2.26 30.05 41.77]
[ 14.5 13.69 33.05]
[ 21.05 38.44 18.1 ]
[ 35.24 1.45 17.65]
[ 67.7 14.89 1.69]]
ind = np.argmin(dist_arr,axis=1)
print ind
[0 1 0 1 2 1 2]
print dist_arr[np.arange(ind.shape[0]),ind]**2
[ 13. 12.29 2.26 13.69 18.1 1.45 1.69]
如果a
和b
为2X5000,而原始代码为135秒,则需要约.3秒。450倍的加速。如果要避免使用scipy获取scipy.spatial.dist
import numpy as np
a = np.random.rand(2,1000)
b = np.random.rand(2,1001)
min_dist = np.sqrt(np.min([np.min(np.sum((b - a[:,i,None])**2, axis=0))
for i in range(a.shape[1])]))
如果要查找a中每个点的最小距离,请将最后一行替换为
min_dists = np.sqrt([np.min(np.sum((b - a[:,i,None])**2, axis=0))
for i in range(a.shape[1])])
如果要避免使用scipy获取scipy.spatial.dist
import numpy as np
a = np.random.rand(2,1000)
b = np.random.rand(2,1001)
min_dist = np.sqrt(np.min([np.min(np.sum((b - a[:,i,None])**2, axis=0))
for i in range(a.shape[1])]))
如果要查找a中每个点的最小距离,请将最后一行替换为
min_dists = np.sqrt([np.min(np.sum((b - a[:,i,None])**2, axis=0))
for i in range(a.shape[1])])
使用此选项是否要求x_data_a
和x_data_b
具有相同的长度(y值相同)?因为这不是我可以对我的数据施加的限制。@Gabriel:不,如果我理解正确的话。如果有一个M点列表和另一个N点列表,可以使用cdist
查找从M中的每个点到N中的每个点的所有距离。这两个列表的长度不必相等。(你要找到的点之间的距离必须有相同数量的组件——也就是说,相同的尺寸——但如果你想找到所有需要的距离,不管怎样。)@Gabriel:我现在看到你的格式了。您需要对其进行转置,以便有XY对列表,而不是单独的X和Y坐标列表。请参阅我编辑的答案。使用此选项是否要求x\u data\u a
和x\u data\u b
具有相同的长度(y值相同)?因为这不是我可以对我的数据施加的限制。@Gabriel:不,如果我理解正确的话。如果有一个M点列表和另一个N点列表,可以使用cdist
查找从M中的每个点到N中的每个点的所有距离。这两个列表的长度不必相等。(你要找到的点之间的距离必须有相同数量的组件——也就是说,相同的尺寸——但如果你想找到所有需要的距离,不管怎样。)@Gabriel:我现在看到你的格式了。您需要对其进行转置,以便有XY对列表,而不是单独的X和Y坐标列表。请看我编辑的答案。请看我在BrenBarn的答案中提出的关于输入列表维度的问题。还有,为什么选择这种元素的特殊配置?我的设置是每个父列表(A和B)中有两个子列表,其中包含x和y值,并且A和B中的x,y对总数不一定相同。@Gabriel:他的示例已经显示了在输入列表中使用不同长度时的情况,正如我在对我的答案的评论中所解释的那样。@Gabriel我已经使用cdist
复制了你的结果,比原始代码快了约400倍。@Ophion我得到了类似的结果,尽管没有你发现的快(我发现了约40倍的加速,但我将答案与一些代码混合在一起),感谢所有的答案!我之所以将此标记为已接受,是因为它比BrenBarn的答案更详细,尽管它们都基于cdist
。干杯。请看我在布伦巴恩的回答中提出的关于输入列表维度的问题。还有,为什么选择这种元素的特殊配置?我的设置是每个父列表(A和B)中有两个子列表,其中包含x和y值,并且A和B中的x,y对总数不一定相同。@Gabriel:他的示例已经显示了在输入列表中使用不同长度时的情况,正如我在对我的答案的评论中所解释的那样。@Gabriel我已经使用cdist
复制了你的结果,比原始代码快了约400倍。@Ophion我得到了类似的结果,尽管没有你发现的快(我发现了约40倍的加速,但我将答案与一些代码混合在一起),感谢所有的答案!我之所以将此标记为已接受,是因为它比BrenBarn的答案更详细,尽管它们都基于cdist
。干杯。为了赢得时间,您可以避免使用np.sqrt
并使用np.argmin
而不是np.min
,然后指向值的索引。接下来只需返回值[index]。(np.sqrt获得时间)@Katsu他想要找到最小距离,所以我必须在某个点进行sqrt,结果是