将2d整数坐标聚类成最多N个点的集合

时间:2011-11-16 01:38:33

标签: algorithm cluster-analysis

我在一个相对较小的二维网格上有许多点,它在两个维度上都包围着。坐标只能是整数。我需要将它们分成最多N个接近在一起的点,其中N将是一个相当小的截止点,我最多只怀疑10个。

我正在为游戏设计一个人工智能,而我99%肯定在所有游戏中使用minimax会给我一个可用的前瞻性约1步,如果那样的话。然而,在我们通过大量动作展望未来之前,遥远的游戏部分应该无法相互影响,所以我想将游戏分成多个N部分的子游戏。但是,我需要确保我一次选择合理的N个部分,即那些靠得很近的部分。

我不关心异常值是自己留下还是与最远距离的群集混在一起。打破大于N的自然集群是不可避免的,只需要合理。因为这用于响应时间有限的游戏AI,我正在寻找尽可能快的算法,并且愿意牺牲性能的准确性。

有没有人对算法有什么建议来适应? K-means和亲戚似乎不合适,因为我不知道我想要找到多少个集群,但我对我想要的集群有多大的约束。我已经看到一些证据表明通过将点捕捉到网格来近似解决方案可以帮助一些聚类算法,所以我希望整数坐标使问题更容易。基于距离的分层聚类将很容易适应环绕坐标,因为我只需插入不同的距离函数,并且相对容易限制聚类的大小。我还应该关注其他任何想法吗?

我对算法比对图书馆更感兴趣,尽管欢迎提供有关其工作方式的良好文档的图书馆。

编辑:当我正在处理Fall 2011 AI Challenge的条目时,我最初问过这个问题,我很遗憾没有完成。我链接的页面有一个相当短的游戏合理的高级描述。

两个关键点是:

  1. 每个玩家都有大量的蚂蚁
  2. 每一只蚂蚁每回合都有命令,向北,向南,向东或向西移动1个方格;这意味着游戏的分支因子是O(4 ants )。
  3. 在比赛中,每个机器人都有严格的时间限制。我曾经想过使用minimax接近游戏(转弯真的是同时发生,但作为一种启发式,我认为它会没问题),但我担心如果我考虑整个游戏,就没有时间向前看很多动作立刻。但是由于每只蚂蚁每回合只移动一个方格,两条蚂蚁不能通过最短路径分开N个空格,可能会相互干扰,直到我们向前看N / 2次移动。

    所以我正在寻找的解决方案是一次选择较小的蚂蚁群并分别对每组进行极小动作的好方法。我原本希望这会让我更深入地搜索移动树而不会失去太多准确性。但显然使用非常昂贵的聚类算法作为节省时间的启发式没有意义!

    我仍然对这个问题的答案感兴趣,尽管我可以从技术中学到更多的东西,而不是这个特别的比赛,因为它结束了!感谢到目前为止的所有答案。

5 个答案:

答案 0 :(得分:6)

中值切割算法在2D中实现非常简单,并且在这里可以很好地工作。你的异常值最终会成为你可以丢弃的1组或者其他任何东西。

要求进一步说明: 中值切割是量化算法,但所有量化算法都是特殊情况聚类算法。在这种情况下,算法非常简单:找到包含所有点的最小边界框,沿着最长边分割框(并缩小它以适合点),重复直到达到目标数量的框。

A more detailed description and coded example

Wiki on color quantization has some good visuals and links

答案 1 :(得分:4)

由于您正在编写一个游戏(我假设),每个复制之间只有一定数量的棋子移动,您可以利用在线算法来获得更新时间。

我相信不会将自己锁定到多个群集的属性称为非平稳

本文接着有一个很好的算法,同时具有上述两个属性:Improving the Robustness of 'Online Agglomerative Clustering Method' Based on Kernel-Induce Distance Measures(您也可以在其他地方找到它。)

以下是a nice video showing算法的工作原理: enter image description here

答案 2 :(得分:1)

在网格上构建图形 G =( V E )并对其进行分区。 由于您对算法而不是库感兴趣,因此这是最近的一篇论文:

  

Daniel Delling,Andrew V. Goldberg,Ilya Razenshteyn和Renato F. Werneck。使用自然切割进行图形分区。在第25届国际并行和分布式处理研讨会(IPDPS'11)上。 IEEE计算机   社会,2011年。[PDF]

来自文字:

  

图分区问题的目标是找到最小成本分区 P ,使每个单元的大小受 U 的限制。

所以你要设置 U = 10。

答案 3 :(得分:1)

您可以计算最小生成树并删除最长边。然后你可以计算k均值。删除另一条长边并计算k均值。冲洗并重复,直到N = 10。我相信这个算法被称为单链路k-means,集群类似于voronoi图:

“单链路k聚类算法......正是Kruskal的算法...等同于找到MST并删除k-1最昂贵的边缘。”

例如,请参见:https://stats.stackexchange.com/questions/1475/visualization-software-for-clustering

答案 4 :(得分:1)

考虑您只需要两个群集的情况。如果你运行k-means,那么你将获得两个点,并且两个簇之间的划分是与两个簇的中心之间的线正交的平面。您可以通过将点向下投影到线上然后将其在线上的位置与阈值进行比较来找出点所在的簇(例如,将线与来自两个簇中心和点之间的矢量的点积相乘)。

对于两个群集,这意味着您可以通过移动阈值来调整群集的大小。您可以沿着连接两个聚类中心的直线对它们的距离点进行排序,然后很容易地沿着线移动阈值,根据聚类的整齐程度来区分拆分的不等式。

您可能没有k = 2,但您可以通过分为两个群集,然后对群集进行细分来分层运行。

(评论后)

我对图片并不擅长,但这里有一些相关的代数。

使用k-means,我们根据它们与聚类中心的距离来划分点,所以对于一个点Xi和两个中心Ai和Bi我们可能感兴趣

SUM_i(Xi-Ai)^ 2 - SUM_i(Xi-Bi)^ 2

这是SUM_i Ai ^ 2 - SUM_i Bi ^ 2 + 2 SUM_i(Bi-Ai)Xi

因此根据K + 2(B-A)的符号将一个点分配给任一簇.X-一个常数加上该向量与点之间的点积和加入两个簇圆的向量。在二维中,最终在一个簇中的平面上的点与在另一个簇中最终的平面上的点之间的分界线是垂直于两个簇中心之间的线的线。我建议的是,为了控制分割后的点数,你为每个点X计算(B - A).X,然后选择一个阈值,将一个簇中的所有点与另一个点中的所有点分开。簇。这相当于在两个聚类中心之间向上或向下滑动分界线,同时保持它垂直于它们之间的线。

一旦你有了点积Yi,其中Yi = SUM_j(Bj - Aj)Xij,一个群集紧密分组的度量是SUM_i(Yi - Ym)^ 2,其中Ym是Yi的平均值。簇。我建议你使用这两个集群的这些值的总和来说明你有多好的分裂。要将一个点移入或移出一个簇并获得新的平方和而不从头开始重新计算所有内容,请注意SUM_i(Si + T)^ 2 = SUM_i Si ^ 2 + 2T SUM_i Si + T ^ 2,所以如果你当你向每个组件添加或减去一个值时,跟踪总和和平方和,你可以计算出一个平方和会发生什么,因为当你添加或删除一个点时,簇的平均值会发生变化。