加速算法在两个二维点数据集中找到最接近的项目

Posted

技术标签:

【中文标题】加速算法在两个二维点数据集中找到最接近的项目【英文标题】:Speeding up algorithm to find the closest items in two data sets of 2D points 【发布时间】:2015-09-18 09:24:31 【问题描述】:

您好,我希望改进这个非常慢的算法。它应该只返回一个点,该点是两个数据集中两个最接近的点之一。

我使用的方法只是蛮力,清楚地测试每组点之间的距离。肯定有更好的办法。

cv::Point FindClosesedValue(std::vector<cv::Point> & point_a, std::vector<cv::Point> point_b)

  double lowest_distance = std::numeric_limits<double>::max();
  cv::Point best_point;
  for (cv::Point & a : point_a)
  
    for (cv::Point & b : point_b)
    
      double distance = CvFunctions::DistanceSquared(b, a);
      if (distance < lowest_distance)
      
        lowest_distance = distance;
        best_point = a;
      
    
  

  return best_point;

请有人指出我加速此代码的正确方法,希望是数量级。示例代码会很棒。

【问题讨论】:

你读过wikipedia吗? 是的,这是一个数据集而不是两个 这两个数据集有多大?您是多次搜索相同的数据集还是每次执行搜索时都搜索不同的数据集? 每个数据集大约有 2000 - 4000 个。我需要用不同的数据集做很多事情。 [OT]:引用可以是const,并且缺少point_b的const ref。 【参考方案1】:

我曾解决过一个类似的问题,我设法获得了 100 倍的加速,但这取决于数据。

如果您可以将一组点预先分类到一个瓦片网格中,您可以利用瓦片大小来缩小您需要测试的点。给定点到特定图块中任何点的最小和最大距离。您可以使用这些最小和最大距离来限制您检查的图块,从而避免检查远处图块中的点。

将点划分为图块后,您可以查找新点将落入哪个图块,然后从那里开始。根据您的数据,图块可能没有预先排序的点。最初,您只想检查第一个图块和周围的图块,直到找到任何点。该点将为您提供最小距离的近似值。一旦你知道你选择的点和找到的点之间的最小距离,你可以继续检查瓷砖中的所有点,直到你选择的点和给定瓷砖中的任何点之间的最小距离大于你找到的最小值。更远的瓷砖中的任何点都不能比您已经找到的点更近。如果您发现新的更近的点,那么该最小距离当然会更新。

排序步骤是O(n),查找步骤在n和n^2之间,所以预期时间最多应该是O(n^2),并且可能要好得多,可能接近线性如果你有一个合适的分数分布。

至于图块大小,我发现选择图块时,每个图块中的点数大致等于覆盖数据集的图块数量,从而产生最佳运行时间。您可能可以使用图块的层次结构做得更好,但我的解决方案从未如此复杂。

【讨论】:

【参考方案2】:

这是一个很好的问题。通常的递归closest pair of points algorithm 显然行不通,因为这两个点集可能聚集在空间的不同区域。

您仍然可以在O(nlogn) 时间内解决此问题。只需为一组中的所有点创建一个 kd-tree (k=2),然后使用另一组中的所有点进行查询。

【讨论】:

请您解释一下为什么usual algorithm 不起作用?我看不到这里违反了 whar 先决条件。 一方面,如果递归的一侧根本没有双色对,那么它应该返回什么值? 我明白了。经典算法适用于单个集合。不在两组之间。

以上是关于加速算法在两个二维点数据集中找到最接近的项目的主要内容,如果未能解决你的问题,请参考以下文章

在二维平面中找到K最近点到点P.

1091.二维矩阵中的最短路径

Python-机器学习-K近邻算法的原理与鸢尾花数据集实现详解

K-近邻算法(KNN)

机器学习k近邻算法

算法:点与点之间欧式距离最小