我正在使用kd-tree算法(found here)来查找矩阵1中相对于矩阵2中所有点的点的最近邻点。上面链接的算法非常快,能够找到使用
在约20秒内使用3E6最近邻居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
答案 0 :(得分: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
你的代码给了我时间.11和1.81。根据上述变化,我得到的标准和半径分别为.69和.28。