【问题标题】:3D clustering Algorithm3D 聚类算法
【发布时间】:2011-03-29 18:30:29
【问题描述】:

问题陈述: 我有以下问题:

3D 空间中有超过十亿个点。目标是在给定距离R内找到具有最多邻居数的前N个点。另一个条件是这些前N个点的任意两点之间的距离必须大于R。这些点的分布不均匀。空间的某些区域包含很多点是很常见的。

目标: 寻找一种可以很好地扩展到许多处理器并且内存需求很小的算法。

想法: 由于分布不均匀,正态空间分解不足以解决此类问题。将点数均分的不规则空间分解可能有助于我们解决问题。如果有人能阐明如何解决这个问题,我将不胜感激。

【问题讨论】:

  • 这听起来像是集合覆盖问题的 3-D 变体!! :-)
  • 你的问题让我想起了“向量量化”,这可能会给你一些想法:data-compression.com/vq.shtml。乍一看,如果去掉这个限制,问题应该不难解决“前N个点的任意两点之间的距离必须大于R”——这个限制导致了很大的问题,并且需要大量思考才能克服它。

标签: algorithm 3d cluster-analysis spatial data-partitioning


【解决方案1】:

使用八叉树。对于具有有限值域的 3D 数据,可以很好地扩展到大型数据集。

上述许多方法,例如 localitysensitive hashing 都是近似版本,专为更高的维度而设计,您无法再进行明智的拆分。

将每个级别拆分为 8 个 bin(2^d for d=3)效果很好。而且由于您可以在单元格中的点太少时停下来,并在其中有很多点非常适合您的要求时构建更深的树。

有关更多详细信息,请参阅维基百科:

https://en.wikipedia.org/wiki/Octree

或者,您可以尝试构建 R-tree。但是 R-tree 试图平衡,使得找到最密集的区域变得更加困难。对于您的特定任务,八叉树的这个缺点实际上很有帮助! R-tree 付出了很多努力来保持树的深度在任何地方都相等,以便可以在大约同一时间找到每个点。但是,您只对密集区域感兴趣,这些区域会在八叉树中最长的路径上找到,甚至无需查看实际点!

【讨论】:

    【解决方案2】:

    我没有给你一个明确的答案,但我有一个可能会产生解决方案的方法的建议。

    我认为值得调查locality-sensitive hashing。我认为将这些点平均分配,然后将这种 LSH 应用于每组应该很容易并行化。如果您设计散列算法,以便按照R 定义存储桶大小,那么对于划分为存储桶的给定点集,满足您条件的点很可能存在于最完整的存储桶中。

    在本地执行此操作后,也许您可​​以应用某种 map-reduce 风格的策略,以逐步方式组合来自不同并行 LSH 算法运行的空间桶,利用您可以开始通过打折整个桶来排除部分问题空间。显然,您必须小心跨越不同存储桶的边缘情况,但我怀疑在合并的每个阶段,您可以应用不同的存储桶大小/偏移量,以便消除这种影响(例如,执行合并空间等效存储桶,以及作为相邻的桶)。我相信这种方法可用于保持较小的内存需求(即,在任何给定时刻,您不需要存储比点本身更多的东西,并且您总是在小(ish)子集上进行操作)。

    如果您正在寻找某种启发式方法,那么我认为这个结果会立即产生类似于“好”解决方案的结果 - 即它会给您提供少量可能的点,您可以检查这些点是否满足您的标准。如果您正在寻找一个确切的答案,那么当您开始合并并行存储桶时,您将不得不应用一些其他方法来修剪搜索空间。

    我的另一个想法是,这可能与查找metric k-center 有关。这绝对不是完全相同的问题,但也许解决时使用的一些方法适用于这种情况。问题是,这假设您有一个metric space,其中计算距离度量是可能的 - 但是,在您的情况下,十亿点的存在使得执行任何类型的全局遍历(例如排序点之间的距离)。正如我所说,只是一个想法,也许是进一步灵感的来源。

    【讨论】:

    • 这确实与最大覆盖问题非常相似。对象功能不同。这里的目标是最小化:Sum((Ci-Ct/K)^2), i = 1,..K,其中 K 是划分的数量,Ci 是集合 i 中的点数,Ct 是总点数。
    • Ci 并不是我们想要优化的变量。但它应该足够接近。理想情况下,Ci 还应包括表面上其最近相邻单元中的点数。由于单元格大小为R,如果距离计算只需要扩展其最近邻单元格即可。
    • 我现在想到的一个想法是创建 LxMxN 个单元格(每个单元格的长度为 R)。可以轻松记录每个单元格的点数。然后可以使用聚类算法来找到密集的聚类。由于点太多,对单个点执行聚类算法是不可行的。但是,我们可以通过将计数除以任意数字来降低 LxMxN 单元中计数的分辨率。例如,Ct/(LMN)。然后可以利用贪心算法进行分区。不确定这是否在正确的轨道上。
    • 我不太确定前两个 cmets 指的是什么。但是,您描述的最后一种方法基本上正是我所建议的 - 某种空间划分(例如 LSH),它允许您计算存储桶中的点以找到您可以检查的合理解决方案(另外,如果您的存储桶大小在R 的术语,那么你实际上可以开始对当前桶和相邻桶中的点进行正常的距离度量)。
    • 前两个cmet与放入网格后数据的分区有关。
    【解决方案3】:

    以下是解决方案的一些可能部分。 每个阶段都有不同的选择, 这将取决于 Ncluster,数据变化的速度, 以及你想用这些手段做什么。

    3 个步骤:量化、框、K-means。

    1) 量化:将输入的 XYZ 坐标减少到每个 8 位, 分别取 X、Y、Z 的 2^8 个百分位数。 这将加快整个流程,而不会丢失太多细节。 你可以对所有的 1G 点进行排序,或者只是随机的 1M, 得到 8 位 x0 8 位 x,展开二分查找很快 — 见宾利,珍珠 p。 95.

    已添加:Kd trees 将任何点云分割成不同大小的盒子,每个盒子都有 ~ Leafsize points — 比上面拆分 X Y Z 要好得多。 但是 afaik 你必须推出你自己的 Kd 树代码 只分割第一个说 16M 的盒子,只保留计数,而不是点。

    2) box:统计每个3d box中的点数, [xj .. xj+1, yj .. yj+1, zj .. zj+1]。 平均盒子会有 2^(30-3*8) 个点; 分布将取决于数据的块状程度。 如果某些框太大或得分太多,您可以 a)将它们分成8个, b) 跟踪每个框中点的中心, 其他范围只取方框中点。

    3) K-means clustering 在 2^(3*8) 盒子中心。 (谷歌并行“k 表示”-> 121k 次点击。) 这在很大程度上取决于 K aka Ncluster,也取决于您的半径 R。 一个粗略的方法是增长一个 heap 在点数最多的 27*Ncluster 盒子中, 然后取最大的受您的半径约束。 (我喜欢从一个 Minimum spanning tree, 然后删除K-1个最长的链接得到K个簇。) 也可以看看 Color quantization.

    我会让 Nbit,这里是 8,从一开始就是一个参数。

    你的 Ncluster 是什么?

    添加:如果您的积分及时移动,请参阅 collision-detection-of-huge-number-of-circles 在 SO。

    【讨论】:

      【解决方案4】:

      我还建议使用八叉树。 OctoMap 框架非常擅长处理巨大的 3D 点云。它不直接存储所有点,而是更新每个节点的占用密度(也称为 3D 框)。 树构建完成后,您可以使用简单的迭代器来查找密度最高的节点。如果您想对节点内的点密度或分布进行建模,OctoMap 很容易采用。

      Here 你可以看到它是如何扩展为使用平面模型对点分布进行建模的。

      【讨论】:

        【解决方案5】:

        只是一个想法。当距离

        这种图的创建类似于空间分解。您的问题可以通过图表中的本地搜索来回答。首先是最大度数的顶点,其次是找到最大度数顶点的最大不连接集。

        我认为图形和搜索的创建可以并行进行。这种方法可能需要大量内存。拆分域并处理较小卷的图形可以减少内存需求。

        【讨论】:

          猜你喜欢
          • 2013-08-26
          • 2020-06-18
          • 2013-11-26
          • 2018-07-24
          • 2020-02-14
          • 2022-01-03
          • 2015-12-09
          • 2011-08-21
          • 2010-11-28
          相关资源
          最近更新 更多