我目前正在尝试找到平衡KD树的所有节点的K最近邻 (K = 2)。
我的实现是来自Wikipedia article的代码的变体,并且找到任何节点 O(log N)的KNN都非常快。
问题在于我需要找到每个节点的KNN。如果我遍历每个节点并执行搜索,那么可以使用大约O(N log N)。
有更有效的方法吗?
答案 0 :(得分:5)
根据您的需要,您可能希望尝试近似技术。有关详情,请查看Arya and Mount关于此主题的工作。一篇关键论文是here。 BigO复杂性详细信息位于'98 paper。
工作的图解说明如下:
来源: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连接算法。但是,在我自己的实验中,他们无法胜过重复的查询。我可能会遗漏一些实施想法。但一般来说,为树连接适当地保存数据比单个查询更加棘手。