AHC
)使用
fastcluster
scipy.cluster.hierarchy
模块功能,in
Python 3
,我发现
cut_tree()
我毫无问题地对数据进行聚类,得到一个链接矩阵,
Z
linkage_vector()
具有
method=ward
. 然后,我想切割dendogram树以获得固定数量的聚类(例如33),我使用
cut_tree(Z, n_clusters=33)
. (请记住,AHC是一种确定性方法,生成一个连接所有数据点的二叉树,这些数据点位于树的叶子上;您可以在任何级别查看此树,以“查看”最终想要的簇数;cut\u tree()所做的一切就是返回一组从0到n\u clusters-1的“n\u cluster”整数标签,归属于数据集的每个点。)
我在其他实验中已经做过很多次了,我总是能得到我要求的集群数量。问题是,当我问这个数据集时
cut_tree()
对于33个集群,它只给了我32个。我不明白为什么会这样。可能是虫子吗?你知道有什么错误吗
? 我试图调试这种行为,并使用scipy的
linkage()
作用将得到的连杆矩阵作为输入
cut_tree()
我没有得到意外数量的集群作为输出。我还验证了两种方法输出的链接矩阵不相等。
[dataset]
我使用的是10680个向量,每个向量有20个维度。检查以下实验:
import numpy as np
import fastcluster as fc
import scipy.cluster.hierarchy as hac
from scipy.spatial.distance import pdist
X = np.load('dataset.npy')
dists = pdist(X)
Z_1 = hac.linkage(dists, method='ward')
Z_2 = fc.linkage_vector(X, method='ward')
print("Z_1 == Z_2 ? ", np.allclose(Z_1, Z_2))
print("Req.\tGot\tequal?")
for i in range(1,50):
cut = hac.cut_tree(Z_2, i)
uniq = len(np.unique(cut))
print(i,"\t",uniq,"\t",i==uniq)
print("Any problem cutting Z_1 for n_clusters in [1,50]? ", not np.all([len(np.unique(
hac.cut_tree(Z_1, i)))==i for i in range(1,50)]))
print("Any problem cutting Z_2 for n_clusters in [1,50]? ", not np.all([len(np.unique(
hac.cut_tree(Z_2, i)))==i for i in range(1,50)]))
您可能已经注意到,数据集包含37个向量,其中至少有一个精确副本,并且计算所有副本时,数据集中总共有55个向量,其中至少有一个副本。
Z_1
在顶部和
Z_2
因此,我再次运行了如前一段代码所示的聚类过程,但这次只使用了包含至少有一个副本的55个向量的数据子集。我获得
X_subset
使用:
uniqs, uniqs_indices, uniqs_count = np.unique(X, axis=0, return_index=True, return_counts=True)
duplicate_rows_indices = list( set(range(len(X))) - set(uniqs_indices) )
number_of_duplicate_rows = len(X)-len(uniqs) # 37
all_duplicate_rows = set()
for i in duplicate_rows_indices:
_rows = set(np.where(X == X[i])[0])
for j in _rows:
all_duplicate_rows.add(j)
rows_with_at_least_a_copy = list(all_duplicate_rows)
number_of_rows_with_at_least_a_copy = len(rows_with_at_least_a_copy) # 55
X_subset = X[rows_with_at_least_a_copy]
因此,fastcluster和scipy不会返回相同的结果,如果只是因为重叠点,那么由于聚类情况的模糊性,这是可以接受的。但问题是
cut_tree()
在这些情况下,当给定通过以下方式获得的链接矩阵时,它有时不会返回请求的簇数:
linkage_vector()
它也张贴在这里:
https://github.com/scipy/scipy/issues/7977
.