【问题标题】:Unsupervised clustering with unknown number of clusters聚类数量未知的无监督聚类
【发布时间】:2012-04-25 13:26:45
【问题描述】:

我有一大组 3 维向量。我需要根据欧几里德距离对它们进行聚类,以使任何特定聚类中的所有向量彼此之间的欧几里德距离都小于阈值“T”。

我不知道有多少个集群。最后,可能存在不属于任何簇的单个向量,因为它与空间中的任何向量的欧几里德距离不小于“T”。

这里应该使用哪些现有的算法/方法?

【问题讨论】:

  • 一定要看看维基百科上的DBSCAN
  • @Anony-Mousse 知道如何从 DBSCAN 获得集群代表吗?
  • DBSCAN 集群可以有任意形状。那么什么才是好的“代表”呢?

标签: algorithm math artificial-intelligence machine-learning cluster-analysis


【解决方案1】:

您可以使用hierarchical clustering。这是一种相当基本的方法,因此有很多可用的实现。例如,它包含在 Python 的 scipy 中。

例如看下面的脚本:

import matplotlib.pyplot as plt
import numpy
import scipy.cluster.hierarchy as hcluster

# generate 3 clusters of each around 100 points and one orphan point
N=100
data = numpy.random.randn(3*N,2)
data[:N] += 5
data[-N:] += 10
data[-1:] -= 20

# clustering
thresh = 1.5
clusters = hcluster.fclusterdata(data, thresh, criterion="distance")

# plotting
plt.scatter(*numpy.transpose(data), c=clusters)
plt.axis("equal")
title = "threshold: %f, number of clusters: %d" % (thresh, len(set(clusters)))
plt.title(title)
plt.show()

这会产生类似于下图的结果。

作为参数给出的阈值是一个距离值,在此基础上决定是否将点/簇合并到另一个簇中。也可以指定使用的距离度量。

请注意,计算集群内/集群间相似度的方法有多种,例如最近点之间的距离,最远点之间的距离,到聚类中心的距离等等。 scipys 层次聚类模块 (single/complete/average... linkage) 也支持其中一些方法。根据您的帖子,我认为您会想使用complete linkage

请注意,如果小(单点)集群不满足其他集群的相似性标准,即距离阈值,则此方法也允许。


还有其他算法会表现得更好,这将在具有大量数据点的情况下变得相关。正如其他答案/cmets 建议的那样,您可能还想看看 DBSCAN 算法:


要对这些和其他聚类算法有一个很好的概述,还可以查看这个演示页面(Python 的 scikit-learn 库):

从那个地方复制的图像:

如您所见,每种算法都对需要考虑的集群的数量和形状做出了一些假设。无论是算法强加的隐含假设还是参数化指定的显式假设。

【讨论】:

  • 但是这种聚类方式不允许孤立向量存在,对吧?根据我在这里写的条件,如果有一个向量与空间中的任何其他向量的欧几里得距离不小于“T”,那么它应该被单独留下。我希望这很清楚 - 抱歉,如果之前没有表达过。
  • @AbhishekShivkumar - 查看我的编辑。当然也可能有单点集群。
  • 然后有人如何找到集群的中心?
  • @Euler_Salter 您按簇排序,按簇分组,然后计算每个簇的点的平均/中值坐标。
【解决方案2】:

moooeeeep 的回答建议使用层次聚类。我想详细说明如何选择聚类的阈值。

一种方法是根据不同的阈值t1t2t3...计算聚类,然后为聚类的“质量”。前提是具有最佳个聚类的聚类质量将具有质量度量的最大值。

我过去使用过的一个优质指标示例是 Calinski-Harabasz。简而言之:您计算平均集群间距离并将它们除以集群内距离。最佳聚类分配将具有彼此分离最多的聚类,以及“最紧密”的聚类。

顺便说一句,您不必使用层次聚类。您还可以使用类似 k-means 的方法,为每个 k 预先计算它,然后选择具有最高 Calinski-Harabasz 分数的 k .

如果您需要更多参考资料,请告诉我,我会在硬盘上搜索一些论文。

【讨论】:

  • 是的,如果有几篇关于 Hierarchical vs Calinski-Harabasz 分数的论文,我会很感激!谢谢
【解决方案3】:

查看DBSCAN 算法。它基于向量的局部密度进行聚类,即它们之间的距离不能超过ε,并且可以自动确定聚类的数量。它还考虑离群值,即 ε-邻居数量不足的点,不属于集群的一部分。维基百科页面链接到一些实现。

【讨论】:

    【解决方案4】:

    使用OPTICS,它适用于大型数据集。

    OPTICS: Ordering Points To Identification the Clustering Structure 与 DBSCAN 密切相关,找到高密度的核心样本并从中扩展集群1。与 DBSCAN 不同,它为可变邻域半径保持集群层次结构。比 DBSCAN 的当前 sklearn 实现更适合在大型数据集上使用

    from sklearn.cluster import OPTICS
    db = OPTICS(eps=3, min_samples=30).fit(X)
    

    根据您的要求微调 eps, min_samples

    【讨论】:

      【解决方案5】:

      您可能没有解决方案:当任何两个不同的输入数据点之间的距离总是大于 T 时,就是这种情况。如果您只想从输入数据中计算聚类数,您可以查看 MCG,具有自动停止标准的层次聚类方法:请参阅https://hal.archives-ouvertes.fr/hal-02124947/document 上的免费研讨会论文(包含参考书目)。

      【讨论】:

        【解决方案6】:

        我想通过使用层次聚类来添加到 moooeeeep 的答案。 该解决方案对我有用,尽管选择阈值非常“随机”。 通过参考其他来源和自己的测试,我得到了更好的方法和阈值可以很容易地被树状图选择:

        from scipy.cluster import hierarchy
        from scipy.spatial.distance import pdist
        import matplotlib.pyplot as plt
        
        ori_array = ["Your_list_here"]
        ward_array = hierarchy.ward(pdist(ori_array))
        dendrogram = hierarchy.dendrogram(hierarchy.linkage(ori_array, method  = "ward"))
        plt.title('Dendrogram')
        plt.xlabel('Customers')
        plt.ylabel('Euclidean distances')
        plt.show()
        

        你会看到这样的情节 click here。 然后通过绘制水平线,假设距离 = 1,连接数将是您想要的集群数。所以这里我为 4 个集群选择了 threshold = 1。

        threshold = 1
        clusters_list = hierarchy.fcluster(ward_array, threshold, criterion="distance")
        print("Clustering list: {}".format(clusters_list))
        

        现在 cluster_list 中的每个值都将是 ori_array 中对应点的指定 cluster-id。

        【讨论】:

          猜你喜欢
          • 2017-05-01
          • 2020-07-21
          • 2019-05-09
          • 2014-06-13
          • 2014-08-06
          • 2018-12-31
          • 2021-10-21
          • 2012-05-14
          • 2019-10-22
          相关资源
          最近更新 更多