我有一个包含数百万个 3D 数据点的数据集。对于我正在做的计算,我需要计算半径中每个数据点的邻居(范围搜索),尝试拟合一个函数,计算拟合误差,对下一个数据点重复此操作,依此类推。我的代码运行正常,但运行时间很长,每个数据点大约需要 1 秒!这可能是因为对于每个点,它必须在整个数据集中进行搜索。有没有办法让这个过程变得更快。我有一个想法,如果我能以某种方式在第一个邻居之间建立一些邻接关系,那么这可以不那么慢。如果有帮助,我正在尝试在 3D 中找到最佳 Parzen 窗口宽度。
对数百万个数据点重复最近邻计算太慢
计算科学
算法
数据结构
最近邻
空间数据
2021-12-20 00:20:25
4个回答
我建议使用谷歌搜索边界体积层次结构(特别是 BSP 树)。给定您的点云,您可以找到一个平面,将其分成两个相等的子云。然后,当您需要找到某个测试点半径 R 内的点集合时,您可以先将您的测试点与该平面进行比较,如果它上方的高度大于 R,则该平面下方的整个子云也必须比 R 更远(所以你不需要检查任何这些点)。你也可以递归地应用这个想法,最终产生 n log n 类型的复杂度而不是 n 平方。(这是 BSP / 二进制空间分区,
这与分子动力学领域的最大挑战之一非常相似——计算非键合粒子之间的所有成对相互作用。
在那里,我们使用单元列表(或邻居列表)来帮助我们找出附近有什么;对于这个应用程序,单元格列表可能是更容易使用的算法:
- 将盒子分成一系列单元格。
- 对于每个粒子,确定应将其分配给哪个单元格(每个粒子 O(1))。
- 然后,对于每个粒子,检查“自己的”单元格和相邻单元格;如果其中任何一个被占用,则无需进一步搜索。
- 如果所有最近的邻居都是空的,则扩展到下一个最近的邻居,依此类推,直到找到一个粒子。
如果您的系统具有或多或少均匀分布的粒子,则根据网格的粗糙度,这将大大降低算法的成本。然而,一些微调是必要的:网格太粗,你不会节省太多时间;太好了,你会花很多时间在空的网格单元上循环!
其它你可能感兴趣的问题