聚类算法性能评估
聚类性能评估(Clustering Evaluation and Assessment)——沙沙的兔子
聚类模型评估——howhigh
参照我的另一篇博文:
第11章 K-means(文档聚类分析)
分类问题,我们可以直接计算被错误分类的样本数量,这样可以直接算出分类算法的准确率。
聚类问题,由于没有标记,所以不能使用绝对数量的方法进行性能评估。
更典型地,针对k-均值算法,我们可以选择k的数值不等于己标记的类别个数。
“熵”,是信息论中最重要的基础概念。熵表示一个系统的有序程度,而聚类问题的性能评估,就是对比经过聚类算法处理后的数据的有序程度,与人工标记的类别的有序程度之间的差异。
1. Adjust Rand Index(调整兰德指数)
Adjust Rand Index是一种衡量两个序列相似性的算法。
优点:
对任意数量的聚类中心和样本数,随机聚类的ARI都非常接近于0;
取值在[-1,1]之间,负数代表结果不好,越接近于1越好;
可用于聚类算法之间的比较。
缺点:
ARI需要真实标签
2. Homogeneity,Completeness,V-measure
同质性homogeneity:每个群集只包含单个类的成员;
完整性completeness:给定类的所有成员都分配给同一个群集;
V-measure:是同质性homogeneity和完整性completeness的调和平均数。
优点:
分数明确:从0到1反应出最差到最优的表现;
解释直观:差的调和平均数可以在同质性和完整性方面做定性的分析;
对簇结构不作假设:可以比较两种聚类算法如k均值算法和谱聚类算法的结果。
缺点:
以前引入的度量在随机标记方面没有规范化,这意味着,根据样本数,集群和先验知识,完全随机标签并不总是产生相同的完整性和均匀性的值,所得调和平均值V-measure也不相同。特别是,随机标记不会产生零分,特别是当簇的数量很大时。
当样本数大于一千,聚类数小于10时,可以安全地忽略该问题。对于较小的样本量或更大数量的集群,使用经过调整的指数(如调整兰德指数)更为安全。
3. Silhouette Coefficient(轮廓系数)
轮廓系数适用于实际类别信息未知的情况。对于单个样本,设a是与它同类别中其他样本的平均距离,b是与它距离最近不同类别中样本的平均距离,其轮廓系数为:
对于一个样本集合,它的轮廓系数是所有样本轮廓系数的平均值。轮廓系数的取值范围是[-1,1],同类别样本距离越相近不同类别样本距离越远,分数越高。
from sklearn import metrics
labels = docs.target
print("Adjusted Rand-Index: %.3f"
% metrics.adjusted_rand_score(labels, kmean.labels_))
print("Homogeneity: %0.3f" % metrics.homogeneity_score(labels, kmean.labels_))
print("Completeness: %0.3f" % metrics.completeness_score(labels, kmean.labels_))
print("V-measure: %0.3f" % metrics.v_measure_score(labels, kmean.labels_))
print("Silhouette Coefficient: %0.3f"
% metrics.silhouette_score(X, kmean.labels_, sample_size=1000))
Adjusted Rand-Index: 0.237
Homogeneity: 0.375
Completeness: 0.554
V-measure: 0.447
Silhouette Coefficient: 0.004
轮廓系数 绘图
%matplotlib inline
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
nb_samples = 1000
X, Y = make_blobs(n_samples=nb_samples, n_features=2, centers=3, cluster_std=1.5)
plt.figure()
plt.scatter(X[:,0], X[:,1],c=Y)
plt.show()
import numpy as np
from matplotlib import cm
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples
fig, ax = plt.subplots(2, 2, figsize=(15, 10))
nb_clusters = [2,3,4,8]
mapping = [(0, 0),(0,1),(1,0),(1,1)]
for i, n in enumerate(nb_clusters):
km = KMeans(n_clusters=n)
Y = km.fit_predict(X)
silhouette_values = silhouette_samples(X,Y)
ax[mapping[i]].set_xticks([-0.15,0.0,0.25,0.5,0.75,1.0])
ax[mapping[i]].set_yticks([])
ax[mapping[i]].set_title('%d clusters' % n)
ax[mapping[i]].set_xlim([-0.15,1])
ax[mapping[i]].grid()
y_lower=20
for t in range(n):
ct_values = silhouette_values[Y==t]
ct_values.sort()
y_upper=y_lower + ct_values.shape[0]
color= cm.Accent(float(t)/n)
ax[mapping[i]].fill_betweenx(np.arange(y_lower,y_upper),0, ct_values, facecolor=color, edgecolor=color)
y_lower= y_upper+20
每个轮廓的宽度与属于特定类的样本数成正比,其形状由每个样本的分数确定。
一个理想的图应该是没有峰值的均匀而且长的轮廓,因为我们期望同一个类的样本之间具有非常低的轮廓分数方差,轮廓分数应该类似于梯形而不是三角形。
对于2个类,形状是可以接受的,但是一个类的平均得分为0.5,而另一个类的得分大于0.75,因此第一个类的内部聚集性较低。图中,当类的数量为8时,则显示了完全不同的情况。所有的轮廓都是三角形的,而且最大分数略大于0.5。这意味着所有的聚类都是内部聚集的,但类之间的分离是不可接受的。当有3个类时,除了第二个类轮廓的宽度外,其他几乎是完美的。如果不考虑其他指标,我们可以通过平均得分认为3个类是最好的选择,但是此时的惯性较低。当有4个类时,情况略差,两个轮廓分数的最大值约为0.5。这意味着其中两个类是完全内部聚集从而可以分离的,而剩下的两个类是相关的并且可能不能很好地分离。现在,我们的选择应该在3到4之间。