仅使用点云作为查询点的D维度中k最近邻搜索的C ++数据结构

时间:2016-05-12 07:09:20

标签: c++ data-structures knn space-partitioning

我在D维空间中有一个具有周期性边界条件的N点的点云,其中N可以在500到10 ^ 8之间,D可以在1到20之间。点的分布变化很大,从完全均匀非常聚集在一起。对于点云中的每个点,我需要找到该点的k个最近邻居。我还需要找出每个点的距离内存在多少个点,特别是最大距离。我不需要知道半径范围内的哪些点,只需要多少,但这将是一个很好的补充。

我尝试过kd-trees,但它们不处理包装边界,对于较大的树,重复是不可行的。此外,它在更高的维度上变慢。

我刚遇到Vantage Point Trees,并尝试了一些代码,但它比kd树慢。虽然我发现的代码使用递归搜索方法,没有批处理。一个积极的方面,它可以原生地处理包装条件,因此不需要重复。

我将要看看是否可以通过转换为迭代方法并查看是否可以批量搜索来从VP树中挤出更多性能,但我有一个想法。所有这些数据结构都可用于查找任意查询点的最近邻居,而我的查询点仅限于点云中的点。我认为这个限制可能允许一些更高性能的结构(可能是各种各样的导航网格?)。我试着寻找可以解决这个问题的结构,但是我的google-fu让我失望了。所以只是想知道是否有人知道可以处理以下内容的数据结构:

  • 处理少量和多个点,即500-10 ^ 8点
  • 最多可处理20个维度
  • 使用周期性边界(即平面圆环)
  • 使用maxnorm距离(软要求.Eurclidean可以给我一个可以手动剔除的潜在列表,但maxnorm会更受欢迎)
  • 可以找到k-NN到查询点,也可以找到距离查询点有多少点
  • 查询点只是结构中的点,而不是任意点
  • 可以批量查询。即我需要找到点云中每个点的第k个NN。我还需要找到每个点i在d [i]内存在多少个点。也就是说,每个点都有不同的搜索半径。
  • 不需要支持插入或删除。

由于

2 个答案:

答案 0 :(得分:2)

我怀疑对你这个非常复杂的问题有一个完整而明确的答案,所以我只是分享我的想法。 您的问题规范结合了许多不能很好地协同工作的事情(高维,非欧几里德度量,完全不同类型的查询)。如果算法必须假设一般情况,则必然很慢。

让我们首先了解已知良好数据结构的特殊情况。

  • 如果您的尺寸为1,请使用有序地图。
  • 如果您的维度为2-3(甚至可能是4),则排序的查找和地理数据库应该是最佳的。 https://en.wikipedia.org/wiki/R-tree
  • 如果您的点具有更高的维度但相关性非常强,则降维可能会将您的点云映射到具有如此低维度的点云,并将问题简化为简单的问题。 https://en.wikipedia.org/wiki/Dimensionality_reduction
  • 如果您的积分数低于10 ^ 6,则蛮力最便宜。只需计算所有点的指标距离,然后对k结果进行部分排序。这些简单的缓存一致性计算比使用树结构更快。 http://en.cppreference.com/w/cpp/algorithm/partial_sort
  • 如果你的k有界,比如k <= 20,并且你优化了查询时间,那就预先计算一个包含所有结果的表格。
  • 如果只有少数维度是周期性的,我认为您应该调整kd-tree算法来处理它们(为那些维度添加更复杂的比较节点,类似于Vantage Point Trees中的维度。)

如果所有这些都不适用(如果您有实际应用,请与我们分享),您的情况非常通用。

除了您提到的算法之外,您还应该尝试几何近邻访问树(GNAT)。 http://infolab.stanford.edu/~sergey/near.html 它们适用于通用指标(包括您的指标),也适用于非均匀分布。

另外,我认为你的期望很高。您可以将一个好的kd-tree实现(例如,https://github.com/mariusmuja/flann)与仅使用欧几里德度量的问题进行比较。如果需要很长时间,则不应期望更快的一般指标能够更快地解决。

不可否认,更通用的方法无法使用您的约束,即查询是云中的点。如果有任何这样的解决方案,我会非常感兴趣。

答案 1 :(得分:0)

如果Java是一个选项(性能类似于现在的C ++),请查看ELKI库。它提供了许多多维索引的实现,包括降维和空间填充曲线的方法。它还为kNN(euclidic / non-euclidic),群集检测,范围查询等提供了许多算法(您通常可以使用自定义距离度量来定义自己的查询过滤器)。 对于kNN,我可以特别推荐CoverTree和(有点慢,但更通用)PH-Tree,我测试了最多27个维度。 PH-Tree特别适用于高度集群和大型数据集(我测试了超过100,000,000个点)。 (免责声明:PH-Tree基于我自己的研究,但我认为您的用例非常合适。)

但据我所知,这些方法都不允许你提出的特殊优化。