使用scipy进行聚类 - 通过距离矩阵聚类,如何获取原始对象

6 投票
1 回答
6129 浏览
提问于 2025-04-17 04:04

我找不到关于在scipy中进行聚类的简单教程或描述,所以我来解释一下我的问题:

我想对文档进行聚类(使用层次聚合聚类),为每个文档创建了一个向量,并生成了一个对称的距离矩阵。vector_list包含了表示每个文档的(非常长的)向量。这个向量列表的顺序和我的输入文档列表是一样的,这样我就可以(希望)将聚类的结果与对应的文档匹配起来。

distances = distance.cdist(vector_list, vector_list, 'euclidean') 

这会生成一个这样的矩阵,其中对角线上的每个元素表示每个文档与自身的距离(总是0)。

[0 5 4]
[5 0 4]
[5 4 0]

我把这个距离矩阵输入到scipy的linkage()函数中。

clusters = hier.linkage(distances, method='centroid', metric='euclidean')

这个函数返回一些我不太明白的东西,但结果是numpy.ndarray类型。根据文档,我可以把这个结果再输入到fcluster中,以获得“扁平聚类”。我使用距离矩阵中最大距离的一半作为阈值。

idx = hier.fcluster(clu,0.5*distances.max(), 'distance')

这又返回一个numpy.ndarray,但我还是不太明白。一个例子是[6 3 1 7 1 8 9 4 5 2]。

所以我的问题是:从linkagefcluster函数中我得到了什么?我该如何从这里回到我最初为其创建距离矩阵的文档,以查看这些聚类是否有意义?我这样做对吗?

1 个回答

3

首先,如果你使用 fclusterdata 而不是 fcluster,那么就不需要经历整个 cdistlinkage 的过程。这个函数可以直接接受一个形状为 (n_documents, n_features) 的数组,这个数组可以是词频、tf-idf 值,或者其他你所用的特征。

fclusterdata 得到的结果和 fcluster 是一样的:你会得到一个数组 T,其中 "T[i] 是原始观察值 i 所属的平面聚类编号。" 也就是说,cluster.hierarchy 模块会根据你设置的阈值(比如 0.5*distances.max())来简化聚类。在你的例子中,第三个和第五个文档被聚在了一起,而其他的文档则各自形成了自己的聚类,所以你可能需要把阈值调高,或者使用不同的 criterion

撰写回答