聚类余弦相似度矩阵

21

在stackoverflow上有一些问题提到了这个问题,但我还没有找到一个具体的解决方案。

我有一个由余弦相似度组成的方阵(值在0和1之间),例如:

  |  A  |  B  |  C  |  D
A | 1.0 | 0.1 | 0.6 |  0.4
B | 0.1 | 1.0 | 0.1 |  0.2
C | 0.6 | 0.1 | 1.0 |  0.7
D | 0.4 | 0.2 | 0.7 |  1.0

方阵可以是任何大小。我想要获得尽可能最大化聚类内部元素之间值的聚类(数量未知)。例如,对于上面的示例,我应该得到两个聚类:

  1. B
  2. A、C、D

原因是C和D之间的值最高,A和C之间的值也最高。

一个项目只能属于一个聚类。

召回率对于这个问题并不那么重要,但精确度非常重要。输出三个聚类是可以接受的:1)B,2)A,3)C,D。但是输出任何将B与另一个元素聚类的解决方案都是不可接受的。

我觉得对角线(1.0)让我感到困惑。我的数据保证至少有一个由两个或更多元素组成的聚类,并且我希望找到尽可能多的聚类而不会牺牲精度。

我将不得不用Python实现这个问题。


1
你尝试过分层聚类吗?这正是你所尝试的,分层凝聚聚类。 - Has QUIT--Anony-Mousse
1个回答

24

您可以使用谱聚类轻松完成此操作。您可以使用现成的实现,例如sklearn中的实现,或者自己实现。这是一个相当简单的算法。

下面是使用sklearn在Python中完成它的代码示例:

import numpy as np
from sklearn.cluster import SpectralClustering
mat = np.matrix([[1.,.1,.6,.4],[.1,1.,.1,.2],[.6,.1,1.,.7],[.4,.2,.7,1.]])
SpectralClustering(2).fit_predict(mat)
>>> array([0, 1, 0, 0], dtype=int32)

正如您所看到的,它返回了您提到的聚类。

该算法获取输入矩阵对应于最大特征值的前k个特征向量,然后在新矩阵上运行k均值算法。以下是一个简单的代码,在您的矩阵上执行此操作:

from sklearn.cluster import KMeans
eigen_values, eigen_vectors = np.linalg.eigh(mat)
KMeans(n_clusters=2, init='k-means++').fit_predict(eigen_vectors[:, 2:4])
>>> array([0, 1, 0, 0], dtype=int32)

请注意,sklearn库中算法的实现可能与我的不同。我给出的示例是最简单的方法。有一些在线教程可以深入介绍谱聚类算法。

对于您希望算法自行确定聚类数量的情况,您可以使用像DBSCAN这样的基于密度的聚类算法

from sklearn.cluster import DBSCAN
DBSCAN(min_samples=1).fit_predict(mat)
array([0, 1, 2, 2])

1
KMeans算法和SpectralClustering都假设聚类数量已知。在我的问题中,聚类数量是未知的,也无法可靠地估计。但感谢您指向sklearn聚类算法。我尝试了它们所有,Affinity Propagation给出了最佳结果。我可能会尝试优化它或尝试创建一个Python模块用于FLAME聚类:https://en.wikipedia.org/wiki/FLAME_clustering - Stefan D
1
我明白。你想要进行聚类而不指定聚类的数量。我现在会在我的答案中添加另一个例子,介绍一种不同于你正在使用的“亲和传播”算法的聚类算法。 - Ashkan
3
谢谢!这个方法是有效的,但不是那么直接。DBSCAN算法假设数据点之间有距离,而余弦相似度则恰好相反。为了让它能够工作,我需要将我的余弦相似度矩阵转换成距离(即从1.00中减去余弦相似度),然后调整eps参数。现在,算法的效果还可以。 - Stefan D
1
@Leo-T,关于你在帖子中提到的谱聚类算法如何工作的问题,我有一个小修正。你说:“该算法取输入矩阵对应于最大特征值的前k个特征向量...”,但实际上它做的恰恰相反。它返回拉普拉斯矩阵对应于k个最小特征值的前k个特征向量。 - user2253546
1
我希望使用特定的余弦相似度截止阈值来对数据进行聚类。是否有任何库可以做到这一点?例如,如果两个向量的余弦相似度小于0.1,则将它们放入同一个簇中。 - Ancalagon BerenLuthien
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接