问题陈述: 我有以下问题:
3D空间中有超过10亿个点。目标是找到在给定距离R内具有最大邻居数的前N个点。另一个条件是那些前N个点中任意两个点之间的距离必须大于R.这些点的分布不均匀。这个空间的某些区域包含很多点是很常见的。
目标: 找到一种可以很好地扩展到许多处理器并且内存需求很小的算法。
思想: 由于不均匀分布,正常的空间分解对于这种问题是不够的。不均匀的空间分解,均匀分割点数可能有助于我们解决问题。如果有人可以解释如何解决这个问题,我将非常感激。
答案 0 :(得分:4)
使用八叉树。对于具有有限值域的3D数据,可以非常好地扩展到大型数据集。
许多上述方法(例如局部敏感哈希)是针对更高维度而设计的近似版本,您无法再进行明智的分割。
将每个级别拆分为8个区域(d = 3时为2 ^ d)非常有效。并且因为当单元格中的点数太少时你可以停下来,并建立一个更深的树,其中有很多点可以很好地满足你的要求。
有关详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Octree
或者,您可以尝试构建R树。但是R树试图平衡,使得找到最密集区域变得更加困难。对于您的特定任务,八叉树的缺点实际上是有帮助的! R树花费了很多精力来保持树的深度在任何地方都相等,因此每个点几乎可以在同一时间找到。但是,您只对密集区域感兴趣,这些密集区域将在Octree最长的路径上找到,而不必查看实际的点!
答案 1 :(得分:2)
我对你没有明确的答案,但我建议采用可能产生解决方案的方法。
我认为值得研究locality-sensitive hashing。我认为均匀地划分点然后将这种LSH应用于每一组应该是容易并行的。如果您设计散列算法,以便根据R
定义存储区大小,则对于分为存储区的给定点集,似乎可能存在满足您的条件的点可能存在于最完整的存储区中。
在本地执行此操作后,您可以应用某种map-reduce-style策略以逐步方式组合来自LSH算法的不同并行运行的空间桶,利用您可以开始的事实通过折扣整个存储桶来排除部分问题空间。显然你必须小心跨越不同桶的边缘情况,但我怀疑在合并的每个阶段,你可以应用不同的桶大小/偏移量,以便你消除这种影响(例如,执行合并空间等效的桶,以及作为相邻的水桶)。我相信这种方法可以用来保持较小的内存需求(即你不需要在任何给定的时刻存储比点本身更多的内容,并且你总是在小(ish)子集上运行)。
如果你正在寻找某种启发式方法,那么我认为这个结果会立即产生类似“好”解决方案的东西 - 即它会给你一些可能的点,你可以检查它们是否满足你的标准。如果您正在寻找确切的答案,那么当您开始合并并行存储桶时,您将不得不应用其他一些方法来修剪搜索空间。
我的另一个想法是,这可能与找到metric k-center有关。这绝对不是完全相同的问题,但也许在解决这个问题时使用的一些方法适用于这种情况。问题在于,假设您有一个metric space,其中可以计算距离度量 - 但是,在您的情况下,十亿点的存在使得执行任何类型的全局遍历(例如排序)变得不可取和困难点之间的距离)。正如我所说,只是一个想法,也许是进一步灵感的来源。
答案 2 :(得分:1)
以下是解决方案的一些可能部分。 每个阶段都有各种选择, 这取决于Ncluster,数据变化的速度, 以及你想用手段做什么。
3步:量化,方框,K-means。
1)量化:将输入XYZ坐标减少到每个8位, 分别取2 ^ 8百分位的X,Y,Z。 这将加速整个流程,而不会造成太多细节损失。 您可以对所有1G点进行排序,或者只是随机的1M, 得到8位x0< x1< ... x256,y0< y1< ... y256,z0< z1< ...... z256 每个范围内有2 ^(30-8)个点。 要映射浮点X - > 8位x,展开的二进制搜索很快 - 见Bentley,Pearls p。 95。
已添加:Kd trees 将任意点云分成不同大小的框,每个框都有~Slansize点 - 比上面拆分X Y Z要好得多。 但是afaik你必须推出自己的Kd树代码 只拆分第一个说16M的盒子,只保留计数,而不是点数。
2)框:计算每个3d框中的点数, [xj .. xj + 1,yj .. yj + 1,zj .. zj + 1]。 平均框将有2 ^(30-3 * 8)点; 分布将取决于数据的集中程度。 如果某些盒子太大或得分太多,你可以 a)将它们分成8个, b)跟踪每个盒子中点的中心, 其他地方只是采取框中点。
3) K-means clustering 在2 ^(3 * 8)盒中心。 (Google平行“k表示” - > 121k点击。) 这很大程度上取决于K aka Ncluster,也取决于您的半径R. 一个粗略的方法是成长a heap 27 * Ncluster箱子中点数最多, 然后选择受Radius约束限制的最大值。 (我喜欢从一开始 Minimum spanning tree, 然后删除K-1最长的链接以获得K个簇。) 也可以看看 Color quantization。
我从一开始就让Nbit(这里是8)参数。
你的Ncluster是什么?
补充:如果您的积分及时移动,请参阅 collision-detection-of-huge-number-of-circles关于SO。
答案 3 :(得分:1)
我还建议使用八叉树。 OctoMap框架非常适合处理巨大的3D点云。它不直接存储所有点,但更新每个节点(也称为3D框)的占用密度。 构建树之后,您可以使用简单的迭代器来查找密度最高的节点。如果您想在节点内建模点密度或分布,OctoMap很容易采用。
Here您可以看到如何使用平面模型对点分布进行建模。
答案 4 :(得分:0)
只是一个想法。当距离<1时,创建具有点之间的给定点和边的图。 R.
这种图的创建类似于空间分解。您可以通过图表中的本地搜索来回答您的问题。首先是具有最大度数的顶点,第二个是找到最大度未连接的最大度顶点集。
我认为图表和搜索的创建可以并行进行。这种方法可能需要大量内存。拆分域并使用图表来处理较小的卷可以减少内存需求。