查找KD树中所有节点的KNN的有效方法

时间:2010-03-26 14:03:16

标签: algorithm nearest-neighbor kdtree knn

我目前正在尝试找到平衡KD树的所有节点的K最近邻 (K = 2)。

我的实现是来自Wikipedia article的代码的变体,并且找到任何节点 O(log N)的KNN都非常快。

问题在于我需要找到每个节点的KNN。如果我遍历每个节点并执行搜索,那么可以使用大约O(N log N)。

有更有效的方法吗?

4 个答案:

答案 0 :(得分:5)

根据您的需要,您可能希望尝试近似技术。有关详情,请查看Arya and Mount关于此主题的工作。一篇关键论文是here。 BigO复杂性详细信息位于'98 paper

工作的图解说明如下:

alt text

来源:http://www.cs.umd.edu/~mount/ANN/Images/annspeckle.gif

我在具有数十万个元素的超高维数据集上使用了他们的库。它比我发现的任何东西都快。该库处理精确搜索和近似搜索。该软件包包含一些CLI实用程序,您可以使用它们轻松地试验数据集;甚至可视化kd树(见上文)。

FWIW:我使用了R Bindings

来自ANN的手册:

  

...... Arya和Mount已经证明了这一点   [AM93b]和Arya等人。 [AMN + 98]那个   如果用户愿意容忍a   搜索中出现少量错误   (返回可能不是的点   最近的邻居,但不是   显着远离   查询点比真正的最近   邻居)然后有可能   实现重大改进   运行时间。 ANN是一个系统   回答最近邻居的查询   完全和近似。

答案 1 :(得分:2)

我使用封面树来解决这个问题。这是链接:http://hunch.net/~jl/projects/cover_tree/cover_tree.html

在50M大小的数据集(所有kNN查询,k = 100)中,封面树创建需要5.5秒,查询需要120秒。 Ann lib用于创建树,需要花费3.3秒,用于查询需要138秒。

已更新:最近邻居不是对称关系。考虑一下:A(0,0)B(1,0)C(3,0)。 B对于C是最接近的,而对于B

,C不是最接近的

答案 2 :(得分:1)

如果节点本身是查询点,则搜索时间可能会更短。您可以从回溯阶段开始,测试的第一个节点已经在查询点附近。然后很快就可以修剪树的大部分区域。

最近邻居是对称关系(如果n1是n2的最近邻居,则同样适用于n2),因此您只需搜索跳过已标记为最近邻居的所有节点的一半节点。只是一个想法。

您还可以尝试KD-Tree BBF(Best-Bin First)搜索,这将帮助您更快地搜索最近的节点(bin)。我已经用C#实现了这个,所以如果你对源代码感兴趣,请写信给我。

当然,实际运行时间取决于维度,KD树结构和数据集中点的分布。

点的聚类也可能是合适的。

答案 3 :(得分:0)

要搜索的字词是 knn join 。更确切地说,你可能想要自我加入。

也许这些搜索结果有帮助:

我只看到了R * -tree的knn连接算法。但是,在我自己的实验中,他们无法胜过重复的查询。我可能会遗漏一些实施想法。但一般来说,为树连接适当地保存数据比单个查询更加棘手。