如何聚类对象(没有坐标)

时间:2009-03-28 00:54:31

标签: algorithm language-agnostic cluster-analysis

我有一个不透明对象列表。我只能计算它们之间的距离(不是真的,只是设置问题的条件):

class Thing {
    public double DistanceTo(Thing other);
}

我想聚集这些对象。我想控制集群的数量,我希望“关闭”对象在同一个集群中:

List<Cluster> cluster(int numClusters, List<Thing> things);

任何人都可以建议(并链接到;-))一些聚类算法(更简单,更好!)或可以帮助我的库吗?

澄清大多数聚类算法都要求在一些N维空间中布置对象。该空间用于查找聚类的“质心”。就我而言,我不知道N是什么,也不知道如何从对象中提取坐标系。 我所知道的是两个对象相距多远。我想找到一个只使用该信息的良好聚类算法。

想象一下,基于对象的“气味”进行聚类。你不知道如何在2D平面上“闻出来”,但你知道两种气味是否相似。

5 个答案:

答案 0 :(得分:6)

我认为您正在寻找K-Medoids。它就像K-means,因为你预先指定了簇的数量 K ,但它并不要求你有一个“平均”你正在聚类的对象的概念,比如K-意思是。

相反,每个群集都有一个代表性的 medoid ,它是最接近中间的群集的成员。您可以将其视为K-means的一个版本,它可以找到“中间人”而不是“手段”。您所需要的只是一个用于聚类事物的距离度量,我在我自己的一些工作中使用它的原因与您引用的原因完全相同。

Naive K-medoids不是最快的算法,但有一些快速的变种可能足以满足您的需要。以下是算法的说明以及R中实现文档的链接:

  1. PAM是K-medoids的基本O(n ^ 2)实现。
  2. CLARA是PAM的快速采样版本。它的工作原理是使用PAM对随机采样的对象子集进行聚类,并根据子集对整个对象组进行分组。你应该仍然能够快速获得非常好的聚类。
  3. 如果您需要更多信息,请here's a paper概述这些和其他K-medoids方法。

答案 1 :(得分:3)

这是一个聚类算法的大纲,它没有找到质心的K-means要求。

  1. 确定所有对象之间的距离。记录 n 大多数单独的对象。
    [找到我们集群的根,时间为O(n ^ 2)]
  2. 将每个 n 随机点分配给 n 新的不同群集。
  3. 对于每个其他对象:
    [将对象分配给群集,时间为O(n ^ 2)]
    1. 对于每个群集:
      1. 通过平均群集中每个对象与对象的距离来计算从群集到该对象的平均距离。
    2. 将对象分配给最近的群集。
  4. 该算法肯定会聚集对象。但它的运行时是 O(n ^ 2)。此外,它还受到所选择的第一个 n 点的指导。

    任何人都可以改进吗(更好的运行时性能,更少依赖于初始选择)?我很想看到你的想法。

答案 2 :(得分:2)

这是一个快速算法。

While (points_left > 0) {
 Select a random point that is not already clustered
 Add point and all points within x distance 
   that aren't already clustered to a new cluster.
}

或者,阅读the wikipedia page。 K-means聚类是一个不错的选择:

  

K-means算法将每个点分配给其中心(也称为质心)最近的聚类。中心是群集中所有点的平均值 - 也就是说,其坐标是群集中所有点上每个维度的算术平均值。

     

算法步骤为:

* Choose the number of clusters, k.
* Randomly generate k clusters and determine the cluster centers, or
  directly generate k random points as cluster centers.
* Assign each point to the nearest cluster center.
* Recompute the new cluster centers.
* Repeat the two previous steps until some convergence criterion is
  met (usually that the assignment hasn't changed).
     

这种算法的主要优点   是它的简单性和速度   允许它在大型数据集上运行。   它的缺点是它没有   每次运行产生相同的结果,   因为产生的集群依赖于   最初的随机分配。它   最小化群内方差,但是   不能确保结果有   全局最小方差。另一个   缺点是要求   可定义的概念   情况并非总是如此。对于这样   数据集k-medoids变体是   合适的。

答案 3 :(得分:1)

这种方法怎么样:

  1. 将所有对象分配到一个群集。
  2. 找到位于同一群集 k 内的两个对象 a b ,这两个对象相距最大距离。为了澄清,整个集合应该有一个 a b ,而不是每个 a b 群集。
  3. 将群集 k 拆分为两个群集, k1 k2 ,一个群集包含对象 a ,另一个群集包含对象 b'/ em>的
  4. 对于群集 k 中的所有其他对象,通过确定与所有其他对象的最小平均距离,将它们添加到 k1 k2 那个集群。
  5. 重复步骤2-5,直到形成N个簇。
  6. 我认为这个算法应该会给你一个相当不错的聚类,尽管效率可能非常糟糕。为了提高效率,您可以更改步骤3,以便找到仅启动群集的原始对象的最小距离,而不是到群集中已有的所有对象的平均距离。

答案 4 :(得分:1)

系统发育DNA序列分析通常在文本字符串上使用层次聚类,具有[比对]距离矩阵。这是一个很好的R群集教程:

(捷径:直接进入“Hierarchical Agglomerative”部分......)

以下是其他一些[语言]库:

这种方法可以帮助确定有多少[k]个“自然”聚类,以及哪些对象可用作上述k-means方法的根。