List1 包含大数(~7 ^ 10)的N维点(N <= 10), List2 包含相同或更少数量的N - 维度点(N <= 10)。
我的任务是:我想检查List2中哪个点最接近(欧几里德距离)到List1中List1中每个点的一个点,然后对它执行一些操作。我一直在做这个简单的嵌套循环方式,当我在List1中没有超过50个点,但是有7 ^ 10个点,这显然占用了很多时间。
最快的方法是什么?计算几何中的任何概念都有帮助吗?
编辑:我有以下内容,我已经用 List2 构建了一个kd-tree然后现在我正在进行每个点的最近邻搜索在 List1 。正如我最初指出的那样, List1 有7 ^ 10点,因此虽然我在蛮力上保存,但每对的欧几里德距离法, List1中的大量点数导致大量时间消耗。有什么方法可以改善这个吗?答案 0 :(得分:5)
好的方法是使用类似kd树的东西并执行最近邻搜索。幸运的是,您不必自己实现此数据结构,之前已经完成了。我推荐这个,但还有其他的:
答案 1 :(得分:2)
如果不了解两种解决方案中点的分布,就不可能告诉你哪种算法效率最高。但是,第一次猜测......
第一种算法不起作用 - 原因有两个:(1)错误的假设 - 我假设边界船体是不相交的,(2)误读了这个问题 - 它没有找到每对点的最短边缘。
...计算两组的凸包:最近的点必须位于两个船体的超曲面上,两个重心之间的直线通过这两个点。
您可以通过计算中心点来计算凸包,假设所有点具有相等的质量,并且从最中心到最远的距离排序列表。然后取出列表中最远的点,将其添加到凸包,然后移除所有计算的凸包内的所有点(您需要计算大量的10d超强度才能执行此操作)。重复unil,列表中没有任何东西不在凸包上。
第二种算法:部分
计算List2的凸包。对于List1的每个点,如果该点位于凸包外,则为第一个算法找到超脸:最近的点必须在此面上。如果它在脸上,同样。如果它在里面,你仍然可以通过从List1延伸超过点的线来找到超脸:最近的点必须在包含到List2的重心的超面的球内:但是,在这里,你需要一个新的算法来获得最近的点,也许是kd-tree方法。
<强>性能比较强>
当List2类似于均匀分布或正态分布时,通过一些相当倾斜的形状,这将很好地减少所考虑的点数,并且它应该与kd-tree建议兼容。
但是有一些可怕的麦芽酒案例:如果List2仅包含圆顶表面上的点,其几何中心是列表的重心,那么凸包的计算成本非常高,并且无济于事在减少所考虑的点数方面做了很多。
我的评价
这些几何技术可能是其他海报的kd-tree方法的有用补充,但在确定它们是否值得应用之前,你需要先了解一点点的分布。
答案 2 :(得分:0)
kd-tree非常快。我在本文中使用了算法,它运行良好Bentley - K-d trees for semidynamic point sets
我确信周围有图书馆,但很高兴知道有时会发生什么 - 宾利解释得很好。
基本上,搜索树的方法有很多种:最近的N个邻居,给定半径内的所有邻居,半径内最近的N个邻居。有时您想搜索有界对象。
这个想法是kdTree以递归方式划分空间。每个节点在您所在空间的一个维度中沿轴向下分成2个。理想情况下,它垂直于节点的最长维度分割。您应该继续分割空间,直到每个桶中有大约4个点。
然后,对于每个查询点,当您递归访问节点时,检查您所在的特定节点与分区墙的距离。如果到达节点的距离,则下降两个节点(您所在的节点及其兄弟节点)分隔壁比搜索半径更近。如果墙超出半径,只需搜索您所在节点的子节点。
当你到达一个桶(叶子节点)时,你测试那里的点,看它们是否在半径范围内。
如果你想要最近的点,你可以从一个巨大的半径开始,并在你递归时传递一个指针或引用 - 这样你就可以在找到近点时收缩搜索半径 - 然后回家最近点非常快。
答案 3 :(得分:0)
(一年后)在看完所有200M点数的1M后,kd树早早退出了, 在高维度上可以更快 结果仅在统计上接近绝对最接近,取决于数据和指标; 没有免费的午餐 (注意,采样1M点,而kd树只有1M,这是完全不同的,更糟糕。)
FLANN对dim = 128的图像数据执行此操作, 我相信opencv。本地模式的快速和坚实 SciPy cKDTree也有cutoff =。