【问题标题】:Unexpected slowdown due to maximum radius in kd-tree nearest neighbour search由于 kd-tree 最近邻搜索中的最大半径而导致意外减速
【发布时间】:2015-04-16 19:59:24
【问题描述】:

我正在使用 kd-tree 算法 (found here) 来查找矩阵 1 中一个点相对于矩阵 2 中所有点的最近邻。上面链接的算法非常快,能够找到最近的 3E6邻居在大约 20 秒内使用

nn2(SetA,SetB,k=1)

现在,我只想包括彼此一定半径内的最近邻居,所以我尝试了

nn2(SetA,SetB,k=1,searchtype='radius',radius=1000)

效果很好,但令人难以置信地减慢了计算速度,实际上是数量级(1000 倍或更多)。我不明白为什么会发生这种情况,因为我认为最大半径实际上应该减少计算时间,因为不必扫描整个空间。

有人能解释一下出了什么问题吗?或者为什么这是预期的行为?

重现行为的示例代码

library(data.table)
library(RANN)
N=50000
DT1=data.table(x=sample(0:300,N,replace=T),y=sample(301:600,N,replace=T))
DT2=data.table(x=sample(0:300,N,replace=T),y=sample(301:600,N,replace=T))

ptm=proc.time()
nnlistV1=nn2(DT1,DT2,k=1)
proc.time()-ptm

ptm=proc.time()
nnlistV2=nn2(DT1,DT2,k=1,searchtype="radius",radius=20)
proc.time()-ptm

【问题讨论】:

  • 听起来很奇怪。 libnabo 呢?
  • 听起来好像正在进行数据转换或nn2 使用的算法效率不高。我的建议是查看源文件rbind.R,其中定义了nn2,并进行复杂性分析。
  • 生成与真实数据集相似的数据集的代码会很有帮助。
  • @ARobertson 好点,我刚刚添加了重现行为的代码

标签: r algorithm


【解决方案1】:

来自ANNmanual

因为它会访问搜索半径内的所有点 一个接一个,如果数 半径范围内的点数很大。

我没有看所有代码,但是annkSearch是你的第一个nn2最终调用的标准代码,而annkFRSearch(FR = Fixed Radius)是上面提到的慢代码。半径版本不受标准约束,完全不同。

运行这个表明在试图找到 k=1 时“半径范围内的点数很大”。

nrow(DT1[DT1$x >= 130 & DT1$x <= 170, ])
[1] 6711

运行一个更适合固定半径搜索的问题,其采样范围更分散,k 大于 1 但略小于范围内可能找到的点:

N=50000
DT1=data.table(x=sample(0:30000,N,replace=T),y=sample(301:60000,N,replace=T))
DT2=data.table(x=sample(0:30000,N,replace=T),y=sample(301:60000,N,replace=T))

nrow(DT1[DT1$x >= 130 & DT1$x <= 170, ])
# I got 70 on my random sample
ptm=proc.time()
nnlistV1=nn2(DT1,DT2,k=50)
proc.time()-ptm

ptm=proc.time()
nnlistV2=nn2(DT1,DT2,k=50,searchtype="radius",radius=400)
proc.time()-ptm

您的代码给了我 0.11 和 1.81 的时间。通过上述更改,标准和半径的时间分别为 0.69 和 0.28。

【讨论】:

  • 谢谢,我现在明白了FR搜索效率低下,因为它访问了半径内的所有点,但我仍然不明白为什么?为什么不只在 kd-tree 算法中实现最大半径标准?这应该不是很难吧?您只需搜索 N 个最近的邻居,然后后验计算您是否要根据半径拒绝其中的一些。还是我错过了一些使这成为不可能的事情?
猜你喜欢
  • 2015-03-17
  • 2012-06-11
  • 2017-03-31
  • 2013-08-02
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-06-27
  • 2015-07-01
相关资源
最近更新 更多