Algorithm 如何利用最近邻搜索算法进行固定半径搜索?

Algorithm 如何利用最近邻搜索算法进行固定半径搜索?,algorithm,nearest-neighbor,range-query,Algorithm,Nearest Neighbor,Range Query,最近邻搜索问题有很多工作要做,所以我想知道如果我想做,我可以利用这些算法进行最近邻搜索吗 也许我可以反复进行第k个最近邻搜索,直到找到半径范围以外的点,但我认为这可能会造成大量浪费。如果只有一个查询,那么这个问题就解决了O(n),其中n是无论如何的点数 若你们有多个查询,那个么这个问题是一个探索性很强的问题,然而它的解决方案比最近邻搜索更复杂。请参阅本文:以d为尺寸数,以r为半径,我知道至少可以使用两种不同的方法: 使用空间散列: 想象一下问题空间被一个大小为s的网格划分成超立方体,这样s=r/

最近邻搜索问题有很多工作要做,所以我想知道如果我想做,我可以利用这些算法进行最近邻搜索吗


也许我可以反复进行第k个最近邻搜索,直到找到半径范围以外的点,但我认为这可能会造成大量浪费。

如果只有一个查询,那么这个问题就解决了O(n),其中n是无论如何的点数


若你们有多个查询,那个么这个问题是一个探索性很强的问题,然而它的解决方案比最近邻搜索更复杂。请参阅本文:

d
为尺寸数,以
r
为半径,我知道至少可以使用两种不同的方法:

使用空间散列: 想象一下问题空间被一个大小为
s
的网格划分成超立方体,这样
s=r/sqrt(d)

关于
s=r/sqrt(d)
的有趣之处在于,这种大小的超立方体中的任意两点都保证位于小于等于
r
的距离

您可以计算网格划分,这样每个超立方体都可以通过其一个角的索引形成的元组来识别。这些索引元组可以用作散列结构(空间散列)的键

现在,这是困难的部分,你必须注意到,对于网格
A
中的任何超立方体,都有一组相邻的超立方体
N=(N1,N2,…)
,它们到给定超立方体的最小距离等于或小于给定半径,几何上看起来像一个超球体。您可以将集合
N
的元素表示为与
A
相关的网格索引的增量。请注意,这些索引增量仅取决于
d

例如,在二维情况下,具有以下几何结构:

   NNN    index deltas:    (-1,  2) ( 0,  2) ( 1,  2)
  NNNNN           (-2,  1) (-1,  1) ( 0,  1) ( 1,  1) ( 2,  1)
  NNANN           (-2,  0) (-1,  0) ( 0,  0) ( 1,  0) ( 2,  0)
  NNNNN           (-2, -1) (-1, -1) ( 0, -1) ( 1, -1) ( 2, -1)
   NNN                     (-1, -2) ( 0, -2) ( 1, -2)
因此,您已经具备了对超球体内的点进行有效搜索所需的一切:

  • 使用包含输入点的超立方体的索引元组作为键,将输入点推入空间散列

  • 给定一个点
    p
    ,搜索的方法是确定它所放置的超立方体
    a
    ,然后使用索引增量集,获得可能包含比
    r
    更近点的相邻超立方体
    N

  • 从空间散列中检索属于超立方体
    N
    的点,并检查哪些点足够接近
    p

  • 有一些额外的优化是可以执行的,因为没有检查A中的点,因为它们保证都足够接近。可以基于
    p
    相对于
    A
    的位置执行N的预过滤

    请注意,选择
    s=r/sqrt(d)
    在拥有小超立方体和不太大的集合
    N
    之间提供了一个很好的折衷方案

    使用k-d树或四元/octo/…-树: 每次在树上向下移动一层时,都会检查它所表示的空间是否与查询超球体相交。如果是这样,你就继续往下看,否则你就完全放弃搜索。

    不仅“最近邻搜索问题有很多工作要做”,而且你的问题还有很多问题要问。最重要的是维度的数量

    如果您不确定尺寸为什么重要,请确保检查我的尺寸


    高维空间

    假设你的点位于一个高维空间中,你应该选择。这个算法的一个很好的实现是。如果您想自己实现它或更好地了解所发生的事情,它们还提供。注意,E²LSH解决了随机版本的R-近邻问题,他们称之为(R,1)− δ) -近邻问题,其中δ与近似值有关,正如他们在中提到的

    你也可以检查我关于LSH的回答。我在C++中使用过它,我强烈推荐它用于你想要执行的固定半径搜索!
    低维空间

    使用CGAL的。对于C++中的这个例子,我已经使用过很多次了。同样,如果您想自己实现,您可以在他们的优秀文档中找到大量信息,并进行相关的谷歌查询



    顺便说一句,答案很好,所以你得到了我的+1.:)

    一个简单的解决方案是在sklearn.neights.KDTree中使用query_radius函数:

    格式为:

    query_radius(X, r, return_distance=False, count_only=False, sort_results=False)
    

    在这种情况下,请参考那篇文章,它对可能的算法进行了广泛的分析。你必须检查所有要点,至少要看看它们的价值观是什么。这是暴力,你可以做得更好。Riko下次,当你回复一条评论时,你可能想标记另一个人,以便他收到通知。使用@otherguy@G.Samaras不,对于一个查询,你做得再好不过了,因为你需要在所有点上迭代一次,只需要得到它们的变量。这就是为什么建立索引会有帮助。请看我的答案。似乎使用网格是最快的方法,但是,我怀疑当搜索半径相对较小或维度较高时,它是否需要大量内存使用。最糟糕的情况是,当每个点都位于不同的超立方体中,并且以包含与点一样多的条目的空间散列结束时,会发生内存使用情况。因此,没有巨大的内存使用。另一方面,集合
    N
    的大小随维数呈指数增长,导致计算成本为
    O(f(M)*exp(d))
    ,其中
    M
    是点数和
    f
    一些待定函数。网格大小不应该设置为
    r
    而不是O
    fr/sqrt(d)
    ?因为使用
    r
    只需在8个相邻的超立方体中加上