#find the nearest point from a given point to a large list of points
import numpy as np
def distance(pt_1, pt_2):
pt_1 = np.array((pt_1[0], pt_1[1]))
pt_2 = np.array((pt_2[0], pt_2[1]))
return np.linalg.norm(pt_1-pt_2)
def closest_node(node, nodes):
pt = []
dist = 9999999
for n in nodes:
if distance(node, n) <= dist:
dist = distance(node, n)
pt = n
return pt
a = []
for x in range(50000):
a.append((np.random.randint(0,1000),np.random.randint(0,1000)))
some_pt = (1, 2)
closest_node(some_pt, a)
#1 楼
如果对距离计算进行矢量化,肯定会更快:点积函数:
def closest_node(node, nodes):
nodes = np.asarray(nodes)
dist_2 = np.sum((nodes - node)**2, axis=1)
return np.argmin(dist_2)
理想情况下,您已经将点列表放置在数组中,而不是列表,这将大大加快速度。 >
评论
\ $ \ begingroup \ $
感谢您的答复,您介意解释为什么这两种方法更快吗?我很好奇,因为我不是来自CS背景
\ $ \ endgroup \ $
– dassouki
13年7月7日在3:28
\ $ \ begingroup \ $
Python for循环非常慢。在矢量的所有项目上使用numpy运行操作时,在C的幕后运行着隐藏的循环,它们的速度要快得多。
\ $ \ endgroup \ $
– Jaime
13年7月7日,下午3:54
#2 楼
您所有的代码都可以被重写为: />如果
randint(1000)
是randint(0, 1000)
(默认值),则结果来自randint
。因此:from numpy import random
from scipy.spatial import distance
def closest_node(node, nodes):
closest_index = distance.cdist([node], nodes).argmin()
return nodes[closest_index]
a = random.randint(1000, size=(50000, 2))
some_pt = (1, 2)
closest_node(some_pt, a)
结果:
a = []
for x in range(50000):
a.append((np.random.randint(0,1000),np.random.randint(0,1000)))
它也快很多(在我的测试中快了二十倍) 。
更重要的是,
high
具有包含None
函数的[0, low)
模块:size
计算距离在两个输入集合的每一对之间。
因此不再需要在循环中计算
randint
。也可以使用for循环来查找最小值的位置,但这可以通过
scipy
对象的scipy.spatial.distance
方法来完成。因此,您的
cdist
函数可以简单地定义为:我比较了此问题中定义的所有cdist(XA, XB, metric='euclidean', p=2, V=None, VI=None, w=None)
函数的执行时间:a = np.random.randint(1000, size=(50000, 2))
所有矢量化函数都执行数百个
distance
的性能仅次于Jaime的第二个功能,但只有一点。肯定是最简单的
argmin
。
评论
我正在研究类似的问题,发现了这一点。同样,Scipy.spatial.KDTree是实现此类方法的方法。可以对表示“列表始终更改”的部分进行扩展,这可能暗示一些提高代码性能的想法。列表是随机更新的,还是每隔几秒钟添加一些点,而有些点会丢失?
如果必须重复搜索同一组点,则scikit-learn中的球树方法可以有效地做到这一点。这些点在预处理步骤中被分类为树形结构,以更快地找到最接近的点。 scikit-learn.org/stable/modules/generation / ...