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
### *Load dataset (10680 vectors, each with 20 dimensions)*
X = np.load('dataset.npy')
### *Hierarchical clustering using traditional scipy method*
dists = pdist(X)
Z_1 = hac.linkage(dists, method='ward')
### *Hierarchical clustering using optimized fastcluster method*
Z_2 = fc.linkage_vector(X, method='ward')
### *Comparissons*
## Are the linkage matrices equal?
print("Z_1 == Z_2 ? ", np.allclose(Z_1, Z_2))
## Is scipy's cut_tree() returning the requested number of clusters when using 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)
## The same as before, but in condensed form. When requesting cut_tree() for clusters
# in the range [1,50] does it return wrong results at some point?
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)]))
#Output:
#
#Z_1 == Z_2 ? False
#
#Req. Got equal?
#1 1 True
#2 2 True
#3 3 True
#4 4 True
#5 5 True
#6 6 True
#7 7 True
#8 8 True
#9 9 True
#10 10 True
#11 11 True
#12 12 True
#13 13 True
#14 14 True
#15 15 True
#16 16 True
#17 17 True
#18 18 True
#19 19 True
#20 20 True
#21 21 True
#22 22 True
#23 23 True
#24 24 True
#25 25 True
#26 26 True
#27 27 True
#28 28 True
#29 29 True
#30 30 True
#31 31 True
#32 32 True
#33 32 False
#34 33 False
#35 34 False
#36 35 False
#37 36 False
#38 37 False
#39 38 False
#40 39 False
#41 40 False
#42 41 False
#43 42 False
#44 43 False
#45 44 False
#46 45 False
#47 46 False
#48 47 False
#49 48 False
#
#Any problem cutting Z_1 for n_clusters in [1,50]? False
#Any problem cutting Z_2 for n_clusters in [1,50]? True
您可能已经注意到,数据集包含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]
#Z_1 == Z_2 ? False
#Req. Got equal?
#1 1 True
#2 2 True
#3 2 False
#4 3 False
#5 4 False
#6 5 False
#7 6 False
#8 7 False
#9 8 False
#10 9 False
#11 10 False
#12 11 False
#13 12 False
#14 13 False
#15 14 False
#16 15 False
#17 16 False
#18 17 False
#19 18 False
#20 20 True
#21 21 True
#22 22 True
#23 23 True
#24 24 True
#25 25 True
#26 26 True
#27 27 True
#28 28 True
#29 29 True
#30 30 True
#31 31 True
#32 32 True
#33 33 True
#34 34 True
#35 35 True
#36 36 True
#37 37 True
#38 38 True
#39 39 True
#40 40 True
#41 41 True
#42 42 True
#43 43 True
#44 44 True
#45 45 True
#46 46 True
#47 47 True
#48 48 True
#49 49 True
#Any problem cutting Z_1 for n_clusters in [1,50]? False
#Any problem cutting Z_2 for n_clusters in [1,50]? True
因此,fastcluster和scipy不会返回相同的结果,如果只是因为重叠点,那么由于聚类情况的模糊性,这是可以接受的。但问题是
cut_tree()
在这些情况下,当给定通过以下方式获得的链接矩阵时,它有时不会返回请求的簇数:
linkage_vector()
它也张贴在这里:
https://github.com/scipy/scipy/issues/7977
.