对数百万个数据点重复最近的邻居计算太慢


14

我有一个数据集,可以在3D模式下运行数百万个数据点。对于我正在进行的计算,我需要计算半径中每个数据点的邻居(范围搜索),尝试拟合函数,计算拟合误差,对下一个数据点重复此操作,依此类推。我的代码可以正常工作,但是运行时间很长,每个数据点大约需要1秒!可能是因为每个点都必须在整个数据集中进行搜索。有没有一种方法可以使该过程更快。我有一个想法,如果我能以某种方式在第一个邻居之间建立某种邻接关系,那么这可能会比较慢。如果有帮助,我试图在3D中找到最佳的Parzen窗口宽度。

Answers:


9

我建议使用谷歌搜索来界定体积层次结构(尤其是BSP树)。给定点云,您可以找到将其分为两个相等的子云的平面。然后,当您需要找到测试点半径R内的点的集合时,可以先将测试点与该平面进行比较,如果它的高度大于R,则该平面下方的整个子云还必须比R更远(因此您无需检查任何这些点)。您也可以递归地应用此想法,最终产生n log n个类型的复杂度,而不是n平方。(这是BSP /二进制空间分区,


7

有几种数据结构用于存储保留有关位置和接近度信息的数据。通过允许快速最近的邻居确定。

特别是R树(和特殊形式,例如R *树)和X树。针对不同用途进行了优化的许多选择。

选择R *树而不是幼稚的最近邻居查找是我从特定代码中获得10000加速因子的很大一部分。(好吧,那也许几百是R * -树,其余大部分是因为幼稚查找受到严重编码,使得它砸了缓存。::叹息::

Øñ日志ññØ日志ñ


5

这与分子动力学领域的最大挑战之一非常相似-计算非键合颗粒之间的所有成对相互作用。

在这里,我们使用单元格列表(或邻居列表)来帮助我们找出附近的事物。对于此应用程序,单元格列表可能是更易于使用的算法:

  • 将框分成一系列单元格。
  • 对于每个粒子,确定应将其分配给哪个单元(每个粒子O(1))。
  • 然后,对于每个粒子,检查“本机”单元格和相邻单元格;如果其中任何一个被占用,则无需进一步搜索。
  • 如果所有最近的邻居都为空,则扩展到下一个最近的邻居,依此类推,直到找到一个粒子。

如果您的系统具有或多或少均匀的粒子分布,则根据网格的粗糙度,这将大大降低算法的成本。但是,必须进行一些微调:网格太粗,您将不会节省太多时间;太好了,您将花费大量时间在空的网格单元上循环!


您应该指出,像元边缘的长度应至少为搜索半径,或者,如果每个粒子都有自己的搜索半径,则应为最大半径。
Pedro

在MD案中是这样;在这里,我们不知道那个半径是先验的
aeismail

长期以来,大型粒子云引力模拟中使用了类似的方案。我不知道它是否仍然是最新技术。
dmckee ---前主持人小猫,

4

您绝对应该检查KD树八叉,它们是点集的选择方法(而BSP用于一般对象,而网格用于或多或少的均匀密度)。它们可以非常紧凑和快速,从而最大程度地减少了内存和计算的开销,并且易于实现。

如果您想尝试网格状的非分层空间细分,则当您的点或多或少均匀地分布时(即使是空的区域,但必须没有密度奇异点或其他高浓度),请检查球体堆积。


3

您可能应该考虑构建Delaunay三角剖分(嗯,它的3D模拟)。在2D中,这是始终包含最近邻居的数据点的特殊三角剖分。在3D中也一样,但在四面体中。

ñ日志ñ

希望能帮助到你!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.