使用scipy进行聚类 - 通过距离矩阵聚类,如何获取原始对象
我找不到关于在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]。
所以我的问题是:从linkage和fcluster函数中我得到了什么?我该如何从这里回到我最初为其创建距离矩阵的文档,以查看这些聚类是否有意义?我这样做对吗?
1 个回答
首先,如果你使用 fclusterdata
而不是 fcluster
,那么就不需要经历整个 cdist
和 linkage
的过程。这个函数可以直接接受一个形状为 (n_documents, n_features)
的数组,这个数组可以是词频、tf-idf 值,或者其他你所用的特征。
从 fclusterdata
得到的结果和 fcluster
是一样的:你会得到一个数组 T
,其中 "T[i]
是原始观察值 i
所属的平面聚类编号。" 也就是说,cluster.hierarchy
模块会根据你设置的阈值(比如 0.5*distances.max()
)来简化聚类。在你的例子中,第三个和第五个文档被聚在了一起,而其他的文档则各自形成了自己的聚类,所以你可能需要把阈值调高,或者使用不同的 criterion
。