集群数量未知的无监督集群


78

我在3维中有大量的向量。我需要基于欧几里得距离对它们进行聚类,以使任何特定聚类中的所有向量之间的欧几里得距离均小于阈值“ T”。

我不知道有多少集群。最后,可能存在不属于任何群集的单个矢量,因为对于空间中的任何矢量,其欧氏距离均不小于“ T”。

在此应使用哪些现有算法/方法?


5
绝对可以DBSCAN在Wikipedia上看看。
已退出-Anony-Mousse 2012年

@ Anony-Mousse有什么想法可以从DBSCAN获得集群代表吗?
Divij Sehgal

DBSCAN群集可以具有任意形状。那么什么是一个好的“代表”呢?
退出了–Anony-Mousse

Answers:


79

您可以使用分层聚类。这是一种相当基本的方法,因此有许多可用的实现。例如,它包含在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分层聚类模块(单个/完整/平均...链接)也支持其中一些方法。根据您的帖子,我认为您想使用完整的链接

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


还有其他一些性能会更好的算法,这些算法在具有大量数据点的情况下将变得有意义。正如其他答案/评论所建议的那样,您可能还想看看DBSCAN算法:


有关这些和其他群集算法的概述,请查看以下演示页面(Python的scikit-learn库的演示页面):

从该位置复制的图像:

http://scikit-learn.org/stable/auto_examples/cluster/plot_cluster_comparison.html

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


但是这种聚类方式不允许存在孤立向量,对吗?根据我在此处编写的条件,如果空间中存在其他向量都不小于“ T”的欧氏距离,则应将其单独放置。我希望这一点很清楚-如果以前没有表达过,对不起。
伦敦家伙

1
@AbhishekShivkumar-看看我的编辑。当然可能会有单点群集。
moooeeeep 2012年

有人如何找到集群的中心?
Euler_Salter '17

@Euler_Salter您可以按聚类进行排序,按聚类进行分组,然后计算每个聚类的各个点的均值/中值坐标。
moooeeeep

21

moooeeeep的答案建议使用分层聚类。我想详细说明如何选择群集的阈值。

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

我过去使用的高质量指标的一个例子是Calinski-Harabasz。简要地说:您可以计算平均群集间距离,并将它们除以群集内距离。最佳聚类分配将具有彼此最分开的聚类和“最紧密”的聚类。

顺便说一句,您不必使用分层群集。您还可以使用类似k -means的方法,为每个k预计算,然后选择Calinski-Harabasz得分最高的k

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


1
是的,您将不喜欢关于分层vs卡林斯基-哈拉巴斯分数的论文!谢谢
更改

11

查看DBSCAN算法。它根据向量的局部密度进行聚类,即它们的距离不得超过ε距离,并且可以自动确定聚类数。它还认为离群点(即,具有不足够数量的ε邻居的点)不属于群集。Wikipedia页面链接到一些实现。


0

使用OPTICS,它可以很好地处理大型数据集。

光学:排序点,以识别与DBSCAN密切相关的聚类结构,找到高密度的核心样本并从中扩展聚类1。与DBSCAN不同,保留集群层次结构用于可变的邻域半径。比目前的DBSCAN sklearn实现更适合用于大型数据集

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

根据您的要求微调eps,min_samples


0

您可能没有解决方案:任何两个不同的输入数据点之间的距离始终大于T就是这种情况。如果只想根据输入数据计算聚类数,则可以看一下MCG,这是一种分层聚类带有自动停止条件的方法:请参阅免费的研讨会论文,网址https://hal.archives-ouvertes.fr/hal-02124947/document(包含书目参考)。


0

我想通过使用层次聚类来添加到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()

您将在此处看到这样的情节 。然后通过画一条水平线,假设在distance = 1处,连词的数量将成为您想要的聚类数量。因此,在这里我为4个群集选择阈值= 1。

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

现在,cluster_list中的每个值将是ori_array中相应点的已分配cluster-id。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.