不同数据结构上最近邻查询的运行时比较
Posted
技术标签:
【中文标题】不同数据结构上最近邻查询的运行时比较【英文标题】:Comparison of the runtime of Nearest Neighbor queries on different data structures 【发布时间】:2014-12-01 23:20:40 【问题描述】:给定d维空间中的n个点,有几种数据结构,如Kd-Trees、Quadtrees等来索引这些点。在这些数据结构上,可以为给定输入点周围的最近邻查询实现直接算法。 是否有书、论文、调查……比较不同数据结构上最近邻查询的理论(大多数预期)运行时间? 我正在查看的数据由相当小的点云组成,因此它们都可以在主内存中进行处理。为了简单起见,我假设数据是均匀分布的。也就是说,我对现实世界的表现不感兴趣,而是对理论结果感兴趣
【问题讨论】:
有几篇有趣的文章,一篇在 sci-kit learn 中,scikit-learn.org/stable/modules/… 并参见 en.wikipedia.org/wiki/Ball_tree 文章中的参考资料。 Kd 树对于高维数据可能表现不佳,但通常对于二维数据非常好。 我已经在 2d 中实现了 kd 树,一个观察结果是,如果您在规则网格上有点,那么当您搜索时算法会失败,因为您无法决定左/右、上/下当点相同时。我首先通过在每个点上添加一个小的随机数来解决它。我还怀疑,虽然随机间隔的网格假设可能是一个很好的起点,但您将无法从这一点清晰地推断到现实世界的点云,这很可能是非常随机的,这就是不同的数据结构和索引方法真正发挥作用。 【参考方案1】:您让点的维度未定义,您只需给出点数的近似值。小是什么意思?一个人所说的小是相对的。
您搜索的内容当然不存在。你的问题差不多是这样的:
问题:
对于一个小的(无论小对你意味着什么)数据集,任何维度的数据遵循均匀分布,最佳数据结构是什么?
回答:
没有这样的数据结构。
对此有答案会不会太奇怪了?一个错误的类比是将“哪种是最佳编程语言?”作为这个问题的同义词。大多数一年级本科生都有的问题。你的问题没有那么幼稚,而是走在了同一个轨道上。
为什么没有这样的数据结构?
因为,数据集的维度是可变的。这意味着,你可能有一个二维的数据集,但也可能意味着你有一个 1000 维的数据集,或者更好的是 1000 维的数据集,intrinsic dimension 远小于 1000。想想它,是否可以提出一种对我提到的三个数据集表现同样好的数据结构?我怀疑。
事实上,有些数据结构在低维中表现得非常好(例如四叉树和 KD-trees),而另一些在高维中表现得更好(例如 RKD-tree forest)。
此外,用于最近邻搜索的算法和期望在很大程度上取决于数据集的维度(以及数据集的大小和查询的性质(例如离数据集太远或与数据集点等距的查询可能会导致搜索性能变慢))。
在较低维度中,可以执行 k-最近邻 (k-NN) 搜索。在更高的维度上,执行 k-Approximate NN 搜索会更明智。在这种情况下,我们遵循以下权衡:
速度 VS 准确度
通过牺牲结果的正确性,我们可以更快地执行程序。换句话说,我们的搜索例程会比较快,但它可能(这种可能性取决于许多参数,例如您的问题的性质和您使用的库)不返回 true NN,而是精确 NN 的近似值。例如,它可能找不到确切的 NN,而是找到查询点的第三个 NN。您也可以查看approximate-nn-searching wiki 标签。
为什么不总是搜索确切的 NN?因为curse of dimensionality,这导致在较低维度中提供的解决方案表现得与蛮力一样好(为每个查询搜索数据集中的所有点)。
你看我的答案已经很大了,所以我应该停在这里。你的问题太宽泛了,但很有趣,我必须承认。 :)
总之,哪种数据结构(和算法)最适合使用取决于您的问题。您正在处理的数据集的大小、点的维度和固有维度起着关键作用。查询的数量和性质也起着重要作用。
【讨论】:
不错的答案。遗憾的是,OP 对理论结果感兴趣,而不是真实世界的结果,使用均匀分布的点云,在未指定的维度上,这有点难以回答。 完全同意@JohnBarça!谢谢:) 感谢您的回答。我猜我并没有真正意识到维度在其中扮演的角色。为此(我现在意识到这个问题太笼统了),我将把它留在这里,而是发布一个更缩小的问题。感谢大家提出维度问题! 有一段时间我也不知道@Skrodde,所以欢迎你。 :)【参考方案2】:对于可能不均匀的点数据的最近邻搜索,我认为 kd-tree 通常会给你最好的性能。就广泛的概述和理论成本分析而言,我认为 Wikipedia 是一个不错的起点,但请记住,它并未涵盖太多现实世界的优化:
http://en.wikipedia.org/wiki/Nearest_neighbor_search
http://en.wikipedia.org/wiki/Space_partitioning
理论性能是一回事,但现实世界的性能完全是另一回事。现实世界的性能取决于数据结构实现的细节,就像它取决于数据结构的类型一样。例如,无指针(紧凑数组)实现可以比基于指针的实现快很多倍,因为改进了缓存一致性和更快的数据分配。如果您利用 SIMD 同时测试多个分支,则较宽的分支在理论上可能会更慢,但在实践中会更快。
此外,您的点数据的确切性质也会对性能产生重大影响。均匀分布的要求不高,可以用更简单的数据结构快速处理。非均匀分布需要更多注意。 (Kd-trees 适用于统一和非统一数据。)此外,如果您的数据太大而无法在内核中处理,那么与较小的数据集相比,您将需要采用完全不同的方法。
【讨论】:
感谢您的回答。但是***不是我可以引用的来源。我宁愿寻找一份科学出版物来使用。为此,我对现实世界的运行时不感兴趣,但真正对均匀分布上理论上预期的运行时感兴趣,该分布小到足以放入主内存。 啊,好吧,我没见过这样的东西。如有必要,自己进行复杂性分析并不难。 只是想知道是否有任何表格或我可以引用的东西。因为它只是与我所做的工作关系不大,所以我宁愿引用它也不愿自己做,但如果那里什么都没有,我想我别无选择。以上是关于不同数据结构上最近邻查询的运行时比较的主要内容,如果未能解决你的问题,请参考以下文章