【发布时间】:2018-06-07 01:51:05
【问题描述】:
我目前正在寻找一种高效算法,该算法从三维空间中获取一组点并将它们分组为类(可能由列表表示)。如果一个点与该类中的一个或多个其他点接近,则它应该属于一个类。如果它们共享任何点,则两个类是相同的。 因为我正在处理大型数据集,所以我不想使用递归方法。此外,我尽量避免使用诸如具有 O(n^2) 性能的距离矩阵之类的东西。
我尝试在网上检查一些算法,但其中大多数并不适用于这个特定目的(例如 k-d 树或其他集群算法)。我曾想过将空间分成更小的部分,但这(可能)会导致结果不准确。
我试图自己写一些东西,但结果证明是有缺陷的。我会在距离之后对我的点进行排序并将距离附加为第四个坐标,然后重复以下代码段:
def grouping_presorted(lst, distance):
positions = [0]
x = []
while positions:
curr_el = lst[ positions[-1] ]
nn_i = HasNeighbor(lst, distance, positions[-1])
if nn_i is None:
x.append(lst.pop(positions[-1]) )
positions.pop(-1)
else:
positions.append(nn_i)
return x
def HasNeighbor(lst,distance,index):
i = index+1
while lst[i][3]- lst[index][3] < distance:
dist = (lst[i][0]-lst[index][0])**2 + (lst[i][1]-lst[index][1])**2 + (lst[i][2]-lst[index][2])**2
if dist < distance:
return i
i+=1
return None
除了(可能很容易修复)溢出错误之外,链接点的逻辑还有一个更大的缺陷。如果您认为我的观点描述了空间中的线,那么该算法仅适用于严格指向原点外部的线,而不适用于圆形或类似结构。
是否有人知道为此预先编写的代码或知道我可以尝试什么?
提前致谢。
编辑:似乎我的拼写以及某些术语的混淆引发了一些误解。我希望这个(糟糕的)草图有所帮助。在这个例子中,我将我的参考距离标记为 d,并用红色圈出了我不希望最终得到的两个容器。
【问题讨论】:
-
另外,为什么不使用 bog-standard k-means 进行两个调整,即质心必须与现有点位于相同的坐标,并且类的成员必须位于设定的最大距离内质心?
-
此外,如果我理解正确并且您想要保证最佳结果(例如,没有随机起始类),则没有有效的算法(除非 P = NP)。
-
@timgeb 我不明白你的意思,这个问题在数学上被明确定义为等价关系。如果两个点的距离小于 d,则它们共享相同的等价类。这意味着每个点都属于一个类。所以不,类不能重叠,因为那样它们的所有点都属于同一个类。请注意,如果这种关系成立,我并没有说它们将仅属于同一类。它们都可能接近第三个点,因此属于同一类。
-
@timgeb no.. 给定“当两个点的距离小于 1 时,它们应该属于同一类”,这意味着 A 和 B 属于同一类,B 和 C 属于同一个类,所以类是 {A,B,C}。编辑:我从来没有说过一个类只包含两点。
-
@timgeb 我尽力澄清所有不确定性。如果您对如何重新表述问题有任何建设性的建议,我很乐意这样做。即使我措辞错误,到目前为止,您所说的只是“这种方式定义不明确”。编辑:我重新考虑,你是对的,它不满足等价关系的定义。我会以不同的方式再试一次:我想将坐标点一起放入容器中。给定一个容器,如果它接近一个或多个当前元素,我想将一个元素放入其中。
标签: python algorithm performance