RI取值范围为[0,1],值越大意味着聚类结果与真实情况越吻合:
如果有了类别标签,那么聚类结果也可以像分类那样计算准确率和召回率。
假设U是外部评价标准,即true_label, 而V是聚类结果,设定4个统计量
符号 | 解释 | 更直白的解释 | 决策正确与否 |
---|---|---|---|
TP / a | 在U中为同一类,且在V中也为同一类别的数据点对数 | 将相似的样本归为同一个簇(同–同) | 正确的决策 |
TN / d | 在U中不在同一类,且在V中也不属于同一类别的数据点对数 | 将不相似的样本归入不同的簇(不同–不同) | 正确的决策 |
FP / c | 在U中不在同一类,但在V中维同一类的数据点对数 | 将不相似的样本归为同一个簇(不同–同) | 错误的决策 |
FN / b | 在U中为同一类,但在V中却隶属于不同类别的数据点对数 | 将相似的样本归入不同的簇(同–不同) | 错误的决策 |
Same Cluster | Different Cluster | Sum U | |
---|---|---|---|
Same Class | TP / a | FN / b | a+b |
Different Class | FP / c | TN / d | c+d |
Sum V | a+c | b+d | a+b+c+d |
RI则是计算“正确决策”的比率,故 R I = T P + T N T P + F P + T N + F N = T P + T N C N 2 = a + b C 2 n s a m p l e s RI=\frac{TP+TN}{TP+FP+TN+FN}=\frac{TP+TN}{C_N^2}=\frac{a+b}{C_2^{n_{samples}}} RI=TP+FP+TN+FNTP+TN=CN2TP+TN=C2nsamplesa+b
分母 C N 2 C_N^2 CN2 和 C 2 n s a m p l e s C_2^{n_{samples}} C2nsamples 皆表示任意两个样本为一类有多少种组合,是数据集中可以组成的总元素对数
调整兰德系数(Adjusted Rand index, ARI), 为什么要引进 ARI呢,因为 RI 的问题在于对两个随机的划分, 其 RI 值不是一个接近于 0 的常数。Hubert和Arabie在1985年提出了调整兰德系数,调整兰德系数假设模型的超分布为随机模型,即 X 和 Y 的划分为随机的,那么各类别和各簇的数据点数目是固定的。
要计算该值, 先计算出列联表(contingency table ), 表中每个值 n i j n_{ij} nij表示某个 document 同时位于 cluster ( Y Y Y) 和 class ( X X X) 的个数, 在通过该表可以计算 ARI 值即可。
A R I = R I − E ( R I ) m a x ( R I ) − E ( R I ) ARI=\frac{RI-E(RI)}{max(RI)-E(RI)} ARI=max(RI)−E(RI)RI−E(RI)
A R I ∈ [ − 1 , 1 ] ARI∈[-1,1] ARI∈[−1,1] 。值越大意味着聚类结果与真实情况越吻合。从广义的角度来将,ARI是衡量两个数据分布的吻合程度的。
adjusted_rand_score
的方法from sklearn import metrics
labels_true = [0, 0, 0, 1, 1, 1]
labels_pred = [0, 0, 1, 1, 2, 2]
# 基本用法
score = metrics.adjusted_rand_score(labels_true, labels_pred)
print(score) # 0.24242424242424246
# 与标签名无关
labels_pred = [1, 1, 0, 0, 3, 3]
score = metrics.adjusted_rand_score(labels_true, labels_pred)
print(score) # 0.24242424242424246
# 具有对称性
score = metrics.adjusted_rand_score(labels_pred, labels_true)
print(score) # 0.24242424242424246
# 接近 1 最好
labels_pred = labels_true[:]
score = metrics.adjusted_rand_score(labels_true, labels_pred)
print(score) # 1.0
# 独立标签结果为负或者接近 0
labels_true = [0, 1, 2, 0, 3, 4, 5, 1]
labels_pred = [1, 1, 0, 0, 2, 2, 2, 2]
score = metrics.adjusted_rand_score(labels_true, labels_pred)
print(score) # -0.12903225806451613