算法的好坏,都要有相应的指标来衡量。尤其聚类的特殊性,也有一些特殊的算法。
衡量指标
这里介绍7种能够用于不同场景下聚类算法的衡量指标:
- 混淆矩阵
- 均一性
- 整性
- V-measure
- 调整兰德系数(ARI)
- 调整互信息(AMI)
- 轮廓系数(Silhouette)
前三个就是混淆矩阵那些。前五个衡量时引入了y,用的比较少,做个了解就可。为什么呢?都有y值了,我完全可以直接用分类,干吗用聚类。轮廓系数用的比较多。
1)混淆矩阵
这里就不提了,前面的文章《机器学习(概述二)——开发流程》 已经做过详细的介绍。
2)均一性(类似正确率)
一个簇中只包含一个类别的样本,则满足均一性;其实也可以认为就是正确率(每个聚簇中正确分类的样本数占该聚簇总样本数的比例和)
p
=
1
k
∑
i
=
1
k
N
(
C
i
=
=
K
i
)
N
(
K
i
)
p=\frac{1}{k} \sum_{i=1}^k \frac{N(C_i ==K_i)}{N(K_i)}
p=k1i=1∑kN(Ki)N(Ci==Ki)
3)完整性(类似召回率)
同类别样本被归类到相同簇中,则满足完整性;每个聚簇中正确分类的样本数占该类型的总样本数比例的和。
r
=
1
k
∑
i
=
1
k
N
(
C
i
=
=
K
i
)
N
(
C
i
)
r=\frac{1}{k} \sum_{i=1}^k \frac{N(C_i ==K_i)}{N(C_i)}
r=k1i=1∑kN(Ci)N(Ci==Ki)
4)V-measure
均一性和完整性的加权平均
V
β
=
(
1
+
β
2
)
⋅
p
r
β
2
⋅
p
+
r
V_\beta = \frac{(1+\beta^2) \cdot pr}{\beta^2 \cdot p + r}
Vβ=β2⋅p+r(1+β2)⋅pr
5)调整兰德系数(ARI)
Rand index(兰德指数)(RI),RI取值范围为[0,1],值越大意味着聚类结果与真实情况越吻合。
R
I
=
a
+
b
C
2
n
s
a
m
p
l
e
s
RI=\frac{a+b}{C_2^{n_{samples}}}
RI=C2nsamplesa+b
其中C表示实际类别信息,K表示聚类结果,a表示在C与K中都是同类别的元素对数(也就是行),b表示在C与K中都是不同类别的元素对数(也就是列),
C
2
n
s
a
m
p
l
e
s
C_2^{n_{samples}}
C2nsamples表示数据集中可以组成的对数,即从样本中取两个.
调整兰德系数(ARI,Adjusted Rnd Index),ARI取值范围[-1,1],值越大,表示聚类结果和真实情况越吻合。从广义的角度来将,ARI是衡量两个数据分布的吻合程度的。
A
R
I
=
(
R
I
−
E
[
R
I
]
)
max
[
R
I
]
−
E
[
R
I
]
E
[
R
I
]
表
示
均
值
ARI=\frac{(RI−E[RI])}{\max [RI]−E[RI]}\quad\quad E[RI]表示均值
ARI=max[RI]−E[RI](RI−E[RI])E[RI]表示均值
6)调整互信息(AMI)
调整互信息(AMI,Adjusted Mutual Information),类似ARI,内部使用信息熵
S
=
{
s
1
,
s
2
,
.
.
.
,
s
N
}
U
=
{
U
1
,
U
2
,
.
.
.
,
U
R
}
V
=
V
1
,
V
2
,
.
.
.
,
V
C
S=\{s_1,s_2,...,s_N\} \quad U=\{U_1,U_2,...,U_R\} \quad V={V_1,V_2,...,V_C}
S={s1,s2,...,sN}U={U1,U2,...,UR}V=V1,V2,...,VC
U
i
∩
U
j
=
V
i
∩
V
j
=
∅
∪
i
=
1
R
U
i
=
∪
j
=
1
C
V
j
=
S
n
i
j
=
∣
U
i
∩
V
j
∣
U_i \cap U_j = V_i \cap V_j = \emptyset \quad \cup _{i=1}^R U_i = \cup_{j=1}^C V_j = S \quad n_{ij} =|U_i \cap V_j|
Ui∩Uj=Vi∩Vj=∅∪i=1RUi=∪j=1CVj=Snij=∣Ui∩Vj∣
P
(
i
)
=
∣
U
i
∣
N
P
(
j
)
=
∣
V
i
∣
N
H
(
U
)
=
−
∑
i
=
1
R
P
(
i
)
log
P
(
i
)
H
(
V
)
=
−
∑
j
=
1
C
P
′
(
j
)
log
P
′
(
j
)
P(i)=\frac{|U_i|}{N} \quad P(j)=\frac{|V_i|}{N} \quad H(U) = -\sum_{i=1}^R P(i) \log P(i) \quad H(V) = -\sum_{j=1}^C P^{'}(j) \log P^{'}(j)
P(i)=N∣Ui∣P(j)=N∣Vi∣H(U)=−i=1∑RP(i)logP(i)H(V)=−j=1∑CP′(j)logP′(j)
M
I
(
U
,
V
)
=
∑
i
=
1
R
∑
j
=
1
C
P
(
i
,
j
)
log
P
(
i
,
j
)
P
(
i
)
P
′
(
j
)
P
(
i
,
j
)
=
∣
U
i
∩
V
j
∣
N
MI(U,V)=\sum_{i=1}^R \sum_{j=1}^C P(i,j) \log \frac{P(i,j)}{P(i)P^{'}(j)} \quad P(i,j)=\frac{|U_i \cap V_j|}{N}
MI(U,V)=i=1∑Rj=1∑CP(i,j)logP(i)P′(j)P(i,j)P(i,j)=N∣Ui∩Vj∣
A
M
I
(
U
,
V
)
=
M
I
(
U
,
V
)
−
E
{
M
I
(
U
,
V
)
}
max
{
H
(
U
)
,
H
(
V
)
}
−
E
{
M
I
(
U
,
V
)
}
AMI(U,V)=\frac{MI(U,V)-E\{MI(U,V)\}}{\max \{ H(U),H(V)\} -E\{MI(U,V)\}}
AMI(U,V)=max{H(U),H(V)}−E{MI(U,V)}MI(U,V)−E{MI(U,V)}
S
S
S 表示整个数据集,
U
U
U 表示整个预测的数据集,
V
V
V 实际数据集(y值),
C
C
C 表示原始的,
R
R
R 表示预测的。
一个样本只属于一个簇,所以
U
i
∩
U
j
=
∅
U_i∩U_j=∅
Ui∩Uj=∅;一个样本只能预测出一种结果,所以
V
i
∩
V
j
=
∅
V_i∩V_j=∅
Vi∩Vj=∅
n
i
j
=
∣
U
i
∩
V
j
∣
n_{ij}=|U_i∩V_j |
nij=∣Ui∩Vj∣,表示实际和预测是相同的个数.
7)轮廓系数(Silhouette)
簇内不相似度:计算样本
i
i
i 到同簇其它样本的平均距离为
a
i
a_i
ai ; $a_i $ 越小,表示样本
i
i
i 越应该被聚类到该簇,簇
C
C
C中的所有样本的
a
i
a_i
ai 的均值被称为簇
C
C
C 的簇不相似度。
簇间不相似度:计算样本
i
i
i 到其它簇
C
j
C_j
Cj 的所有样本的平均距离
b
i
j
b_{ij}
bij ,
b
i
=
min
{
b
i
1
,
b
i
2
,
.
.
.
,
b
i
k
}
b_i =\min \{b_{i1} ,b_{i2} ,...,b_{ik}\}
bi=min{bi1,bi2,...,bik};
b
i
b_i
bi 越大,表示样本
i
i
i 越不属于其它簇。
轮廓系数:
s
i
s_i
si 值越接近 1 表示样本
i
i
i 聚类越合理,越接近 -1,表示样本i应该分类到另外的簇中,近似为 0,表示样本i应该在边界上;所有样本的
s
i
s_i
si 的均值被成为聚类结果的轮廓系数.
s
(
i
)
=
b
(
i
)
−
a
(
i
)
max
{
a
(
i
)
,
b
(
i
)
}
s(i)=\frac{b(i)−a(i)}{\max \{a(i),b(i)\}}
s(i)=max{a(i),b(i)}b(i)−a(i)
s
(
i
)
=
{
1
−
a
(
i
)
b
(
i
)
,
a
(
i
)
<
b
(
i
)
0
,
a
(
i
)
=
b
(
i
)
b
(
i
)
a
(
i
)
−
1
,
a
(
i
)
>
b
(
i
)
s(i)=\begin{cases} 1-\frac{a(i)}{b(i)}, a(i)<b(i)\\ 0, a(i)=b(i)\\ \frac{b(i)}{a(i)}-1, a(i)>b(i)\\ \end{cases}
s(i)=⎩⎪⎨⎪⎧1−b(i)a(i),a(i)<b(i)0,a(i)=b(i)a(i)b(i)−1,a(i)>b(i)
我们希望的是最终结果越趋近于1越好
代码
基于scikit包中的创建模拟数据的API创建聚类数据,对K-Means算法和Mini Batch K-Means算法构建的模型进行评估。
API
调整兰德系数(ARI):sklearn.metrics.adjusted_rand_score(labels_true, labels_pred)
- labels_true表示实际的
- labels_pred表示预测的
V-measure:sklearn.metrics.v_measure_score(labels_true, labels_pred, beta=1.0)
调整互信息(AMI):sklearn.metrics.adjusted_mutual_info_score(labels_true, labels_pred, average_method=‘arithmetic’)
互信息(MI):sklearn.metrics.mutual_info_score(labels_true, labels_pred, contingency=None)
代码
我们采用上篇博客相同的内容。
import time
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn import metrics
from sklearn.metrics.pairwise import pairwise_distances_argmin
from sklearn.datasets.samples_generator import make_blobs
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
centers = [[1, 1], [-1, -1], [1, -1]]
clusters = len(centers)
X, Y = make_blobs(n_samples=3000, centers=centers, cluster_std=0.7, random_state=28)
Y # 在实际工作中是人工给定的,专门用于判断聚类的效果的一个值
### TODO: 实际工作中,我们假定聚类算法的模型都是比较可以,最多用轮廓系数/模型的score api返回值进行度量;
### 其它的效果度量方式一般不用
### 原因:其它度量方式需要给定数据的实际的y值 ===> 当我给定y值的时候,其实我可以直接使用分类算法了,不需要使用聚类
array([2, 0, 0, …, 2, 2, 1])
k_means = KMeans(init='k-means++', n_clusters=clusters, random_state=28)
t0 = time.time()
k_means.fit(X)
km_batch = time.time() - t0
print ("K-Means算法模型训练消耗时间:%.4fs" % km_batch)
K-Means算法模型训练消耗时间:0.0981s
batch_size = 100
mbk = MiniBatchKMeans(init='k-means++', n_clusters=clusters, batch_size=batch_size, random_state=28)
t0 = time.time()
mbk.fit(X)
mbk_batch = time.time() - t0
print ("Mini Batch K-Means算法模型训练消耗时间:%.4fs" % mbk_batch)
Mini Batch K-Means算法模型训练消耗时间:0.0460s
km_y_hat = k_means.labels_
mbkm_y_hat = mbk.labels_
print(km_y_hat) # 样本所属的类别
[0 2 2 … 1 1 0]
k_means_cluster_centers = k_means.cluster_centers_
mbk_means_cluster_centers = mbk.cluster_centers_
print ("K-Means算法聚类中心点:\ncenter=", k_means_cluster_centers)
print ("Mini Batch K-Means算法聚类中心点:\ncenter=", mbk_means_cluster_centers)
order = pairwise_distances_argmin(k_means_cluster_centers,
mbk_means_cluster_centers)
order
K-Means算法聚类中心点:
center= [[-1.0600799 -1.05662982]
[ 1.02975208 -1.07435837]
[ 1.01491055 1.02216649]]
Mini Batch K-Means算法聚类中心点:
center= [[ 0.99602094 1.10688195]
[-1.00828286 -1.05983915]
[ 1.07892315 -0.94286826]]
array([1, 2, 0], dtype=int64)
### 效果评估
score_funcs = [
metrics.adjusted_rand_score,#ARI
metrics.v_measure_score,#均一性和完整性的加权平均
metrics.adjusted_mutual_info_score,#AMI
metrics.mutual_info_score,#互信息
]
## 2. 迭代对每个评估函数进行评估操作
for score_func in score_funcs:
t0 = time.time()
km_scores = score_func(Y,km_y_hat)
print("K-Means算法:%s评估函数计算结果值:%.5f;计算消耗时间:%0.3fs" % (score_func.__name__,km_scores, time.time() - t0))
t0 = time.time()
mbkm_scores = score_func(Y,mbkm_y_hat)
print("Mini Batch K-Means算法:%s评估函数计算结果值:%.5f;计算消耗时间:%0.3fs\n" % (score_func.__name__,mbkm_scores, time.time() - t0))
K-Means算法:adjusted_rand_score评估函数计算结果值:0.72526;计算消耗时间:0.199s
Mini Batch K-Means算法:adjusted_rand_score评估函数计算结果值:0.72421;计算消耗时间:0.002s
K-Means算法:v_measure_score评估函数计算结果值:0.65754;计算消耗时间:0.011s
Mini Batch K-Means算法:v_measure_score评估函数计算结果值:0.65780;计算消耗时间:0.003s
K-Means算法:adjusted_mutual_info_score评估函数计算结果值:0.65726;计算消耗时间:0.026s
Mini Batch K-Means算法:adjusted_mutual_info_score评估函数计算结果值:0.65757;计算消耗时间:0.006s
K-Means算法:mutual_info_score评估函数计算结果值:0.72231;计算消耗时间:0.003s
Mini Batch K-Means算法:mutual_info_score评估函数计算结果值:0.72264;计算消耗时间:0.002s