适用于移动物体的近似增量最近邻算法

19

悬赏

这个问题涉及到几个问题。将会悬赏给一个综合解决这些问题的答案。


这是一个我一直在探索的问题。

注意:我尤其感兴趣的是不基于欧几里得空间的解决方案。

有一组演员组成了大小为K的人群。任意两个演员之间的距离d(ActorA,ActorB)可以轻松计算出来(解决方案应该适用于各种距离的定义),我们可以使用多种已建立的算法找到任何给定演员的N个最近邻的集合。

这个邻居集在第一时间是正确的,但是演员总是在移动,我想要维护每个演员N个最近邻居的不断更新列表。我感兴趣的是比完美解决方案更高效的近似解决方案。

  1. 解决方案应该在引入错误后收敛到正确性
  2. 如果误差变得太大,有时执行完整的重新计算是可以接受的,但是检测这些错误应该是廉价的

到目前为止,我一直在使用朋友之友算法:

recompute_nearest (Actor A)
{
    Actor f_o_f [N*N];
    for each Actor n in A.neighbours
        append n to f_o_f if n != A and n not in f_o_f

    Distance distances [N*N];
    for 0 <= i < f_o_f.size
        distances [i] = distance (A, f_o_f [i])

    sort (f_o_f, distances)
    A .neighbours = first N from f_o_f
}

当人群移动缓慢且N足够大时,这个函数表现良好。它在小误差后收敛,满足第一个标准,但是

  • 我没有好的方法来检测大误差,
  • 我没有对误差大小和频率的定量描述,
  • 虽然实际上它收敛了,但我不能证明它总是会。

您能帮忙解决这些问题吗?

此外,您知道有哪些替代方法可以在以下情况下表现良好吗:

  • 当人群移动较快时,
  • 有些参与者移动较快时,
  • 当N较小时,
  • 当某些地方人群稀疏,而某些地方人群密集时,
  • 还有特定的空间索引算法吗?

我目前正在进行的扩展是将朋友的朋友推广到在邻居移动较快的情况下考虑朋友的朋友。我怀疑这不会很好地扩展,并且很难在没有误差量化的情况下导出正确的参数。

欢迎所有建议!这是一个有趣的小问题:-)


目前的建议

Fexvez:随机采样额外邻居,采样大小取决于参与者的速度。从它即将移动到的区域进行采样可能也会有帮助。

当代理的speed*delta_time超过到最远已知邻居的距离时,重新采样邻居。

维护Delaunay三角剖分,它是最近邻图的超集。 仅适用于一个最近邻居。

David Mount的ANN库 似乎不能处理移动体。


问题的维度是什么? - Don Reba
1
我将“距离”定义为2D/3D欧几里得距离和任意高维模糊集成员的组合(实际上,维度小于10)。 - spraff
你有最大的K值吗?distance()是唯一的函数吗?还是可以计算演员的路径或下一个位置,或通过比较后续位置合理地估计它的路径?例如,是否可以计算每个演员,如果它们当前的路径保持不变,则其他演员永远无法成为更近的邻居?这已经在星系模拟器内解决了吗?你的人群像鸟群或大中央楼层上的旅客或其他什么东西?也就是说,你有多少(粗略)指标表明有多少演员的最近邻居会发生变化?通过“更有效”您的意思是更快吗?内存是免费的吗? - joe snyder
没有最大K值;距离是唯一的精确度量(在某些情况下可能存在启发式算法);您可以假设每个时间步内的运动平稳,但速度是动态的;在这个特定的应用中,它更像是旅行者而不是一群鸟(N群混合可能是一个有趣的模型),而“高效”指的是时间而不是空间。 - spraff
剩下的赏金时间不够多,所以我只能提供这个想法:在每个步骤之间猜测每个角色的向量,并为每个角色保留未来可能最近邻居的列表(“他正在朝我走来”与“他正在远离我,永远不可能更近”),按距离排序,随时更新任何人改变方向。每个角色的候选人数可能仍然足够小,以便快速处理,并且您可能会长时间地只更新更近的候选人。首先只做二维,以查看可以应用多少技巧。 - Witness Protection ID 44583292
优化您的距离函数(或估计它),使用“平方距离”(例如,对于欧几里得距离忽略平方根)。这将提高您选择的任何方法的性能。 - Louis Ricci
7个回答

10

从统计学的角度来看,一种非常简单快速的方法是使用随机线性投影(RLP)。这些可以帮助您快速确定聚类和邻居。使用更多投影,您可以获得更高的精度(关于错误的问题,我相信这样做可以解决)。

这篇论文提供了对几种方法进行广泛的定量分析,其中包括一种与RLP相关的新方法(DPES)。

这篇论文讨论了使用RLP的方法,甚至在移动点的情况下也能保持距离。

这篇论文介绍了用于运动规划的RLP,并详细说明了几种启发式方法。

RLP方法:

  1. 非常快速
  2. 导致可调节精度和速度的近似值
  3. 距离和角度可以保留(可以证明)
  4. 容易扩展到大维数和大数量的对象
  5. 用于降维非常有用
  6. 导致紧凑的投影(例如,可以投影到层次二进制分区)
  7. 灵活:您可以将其投影到认为合适的任何空间中 - 通常是R^d,但是可以将其投影到2^d(即维数d的二进制空间),只是对于给定数量的投影会降低精度。
  8. 在统计学上很有趣

在嵌入到较低维空间后,邻居计算非常容易,因为在同一区域中被分组(如果您将投影分组到网格中)的投影很可能接近原始空间中的投影。

尽管原始数据的维数很小(甚至10也很小),但快速投影到预选网格的能力非常有用,以便识别并计算邻居。

最后,您只需要更新那些位置已更改的对象(或相对位置,如果您正在居中和缩放数据)。

有关相关作品,请查阅Johnson-Lindenstrauss引理。


多么美妙的技巧啊!不知道它是否解决了楼主的问题,但我很高兴学到了它。 - Martin DeMello
2
请在引用任何论文时始终提供完整的参考文献:网页链接会随时间而失效!上面的第一个和最后一个已经失效了。 - olefevre

4

你尝试过使用四叉树吗?

也就是说,将“世界”递归地分割成每个具有四个子节点的图形。然后,树可以快速检查哪些对象在世界的特定正方形内并丢弃其余对象。这是一种非常有效的修剪技术,通常用于提高游戏中碰撞检测的性能。

如果这是3D,则将其扩展为八叉树。


4
谢谢,我知道空间索引。这种方法可以加快完全准确的方法,但当距离函数不平凡时会变得复杂(演员不像点一样)。 - spraff
你能详细解释一下吗?在开始计算距离之前,似乎先剔除大部分对象应该会使它更快,至少我这样做时是这样的 :-) - Martin Wickman
2
当您从上到下搜索一个点时,八叉树的搜索效果很好。但是,当您从底部横向跨越一个区域时,就会出现问题。考虑从靠近角落的点开始--在另一侧的四分之一将必须对称地向上扩展到根部、向外和向下。如果我们利用时间相干性,就可以避免这种情况。您正在谈论如何使一种方法更快,而我正在寻找多种方法以及如何在它们之间进行选择。 - spraff

4
这里有一个简单的反例,可以说明你的朋友的朋友算法有时会错过邻居:从许多(至少超过3 * N)等距离间隔的演员构成的一条长直线开始,逐渐将该线弯曲成圆。如果这条线足够长,其中的演员将不会检测到其邻域内的任何本地变化;特别是在两端的演员相遇时,他们也不会注意到。 编辑:实际上,我想到了一个更简单的反例:取N个或更多演员组成的两个孤立的紧凑群集,并让它们相互碰撞。

谢谢您的关注。是的,像这样的病态情况会破坏我的当前方法。有没有什么提示可以检测这些情况? - spraff
1
嗯,偶尔进行全局重新计算显然可以解决它们。像Martin Wickman建议的基于空间分割的方法也行。另外,如果你跟踪演员的Delaunay三角剖分,而不是(或除了)他们的N个最近邻居,这种问题就不会出现。 (当然,更新三角剖分本身就是一项不容易的任务,但显然有相当快速的算法可用。) - Ilmari Karonen

3
我有一个看起来像解决方案的东西。
在每个“重新计算”步骤中,它需要线性时间,我猜这不是太大的问题,因为你为每个演员执行了recompute_nearest (Actor A)
让我们来谈谈:对于每个演员,在计算recompute_nearest (Actor A)之前,添加一定数量的随机朋友的想法。这个数字不应该太小,否则你永远无法检测到错误。它也不应该太大,否则计算邻居的邻居就是二次的,计算成本将太高。
但是,“不太小”或“不太大”意味着什么?我们将从一个演员A开始,看看他的邻居列表如何更新。假设对于每个点,您添加原始K个演员的p百分比。然后,如果另一个点B靠近A但不是朋友的朋友,则应通过“随机朋友”来“快速”添加他。在每次迭代中,有(1-p)的机会不选择他。
快速计算表明,如果您想在90%的情况下在10次迭代内发现此点,则需要p=20%。这非常昂贵。

然而,一切都没有失去!我想要说的第一点是,如果错误倾向于“一起出现”,那么性能会显著提高!想象一下最初相距很远的两个斑点(人们聊天,星团等…)如果这些斑点碰撞,则朋友的朋友永远不会看到存在问题。但是,通过我的算法,如果您发现一个单独的错误,并正确地调整了邻居列表,则朋友的朋友算法将纠正所有剩余的错误。
如果您有K=1,000并且有两个仅包含1%点的小斑点,并且您希望在10次迭代或更少的时间内以99%的确定性发现,则可以计算出您只需要p=1%! (K越大,p需要越小!)好吧,假设一些点“在一起”。
我还有另一个优化:调整随机点的数量和质量。简单地说,快速演员应该比慢演员拥有更多的随机朋友。您应该随机这些朋友,更喜欢其他快速演员。我无法量化它,但您可以猜测为什么它会提高性能!
关于您的问题“演员速度快时我该怎么办”有一个小修改:您可以通过给自己发现错误的步骤数来衡量演员的速度。我的意思是,如果您认为每个演员周围都有他的朋友圈,那么这个理论上的圆圈对应于他的朋友列表。如果大多数演员在10次迭代中无法完全穿过这个圆圈,但可以在15次迭代中穿过,那么您应该考虑给自己10次迭代来发现问题。如果您的演员如此之快以至于可以在3步内穿过这个“圆圈”,那么...这个算法不适合您(并且我想试图保持邻居列表而不重新计算它可能是一种幻想)。
从根本上讲,保持邻居列表表明存在某种结构(即两次迭代之间大致相同的东西)。速度则相反,快速演员意味着您没有结构。对于非常快的演员,保持邻居列表可能不是一个好主意。
关于斑点的技术细节。
您有两个包含每个演员的%的斑点(大小为sK)(示例为s = 1%
您给自己一个e%的误差范围(例如1%)和n步骤(例如10)
然后,存在p的上限:p <= [log(1-e^(1/n))]/[s*K²*log(1-s)] 我的示例的真实值是p <= 0.989%
如果s很小而K很大,则p等于p = [log(1-e^(1/n))]/[s*K²*log(1-s)]。如果不是这种情况,p要小得多!

1

我的尝试方案。

  1. 覆盖树作为基础数据结构进行kNN。特点:不需要欧几里得度量,线性空间使用,当数据的内在维度固定时,kNN/插入/删除都是O(log n)。非特征:运动。

  2. 为了处理移动对象,周期性地,对于每个对象,删除其旧位置,插入其新位置,并找到kNN。

如果我们将一个对象的周期设置为与速度成反比,那么我们知道覆盖树和现实之间的最大差异受到常数的限制。


0

KD树允许您在固定半径内高效搜索点。如果一个点的所有邻居都在d1单位内,且任何点从上次测量的最大位移为d2,则您只需要在该点的d1+d2单位范围内进行搜索。

如果您正在处理闵可夫斯基距离,则可以使用David Mount的ANN库。不过我不确定是否有一个库可以使用任意距离函数。


0

当一个Actor在给定的时间步长内移动的距离超过它最远已知邻居的距离时,重新采样所有的邻居。

另一个触发器:当Actor自上次重新采样以来移动的距离超过最远已知邻居的距离时,重新采样。

在这里进行微小的优化是很好的,如果有一个分层空间索引,请搜索包含a)半径等于跳跃大小的球体和b)至少N个Actor的节点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接