计算两个聚类结果的聚类精度
Calculate cluster accuracy of two clustering outcomes
假设我有两个如下所示的聚类结果:
clustering = [[8, 9, 10, 11], [14, 13, 4, 7, 6, 12, 5, 15], [1, 2, 0, 3]]
correct_clustering = [[2, 8, 10, 0, 15], [12, 13, 9, 14], [11, 3, 5, 1, 4, 6, 7]]
我将如何比较 clustering
中包含的结果与 correct_clustering
中包含的结果。我想要一个介于 0 和 1 之间的数字。我正在考虑计算在同一簇中正确聚集在一起的对的分数。但是想不出一个程序化的方法来解决这个问题。
您可以在sklearn
中使用函数adjusted_rand_score
:
from sklearn.metrics import adjusted_rand_score
clustering = sorted((i, num) for num, lst in enumerate(clustering) for i in lst)
clustering = [i for _, i in clustering]
# [2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]
correct_clustering = sorted((i, num) for num, lst in enumerate(correct_clustering) for i in lst)
correct_clustering = [i for _, i in correct_clustering]
# [0, 2, 0, 2, 2, 2, 2, 2, 0, 1, 0, 2, 1, 1, 1, 0]
ari = adjusted_rand_score(correct_clustering, clustering)
# -0.012738853503184737
函数 returns 的值介于 1 和 -1 之间,因此要获得介于 0 和 1 之间的值,您需要重新缩放:
ari_scaled = (ari + 1) / 2
# 0.49363057324840764
最佳实践措施确实基于配对计数。
特别是调整后的兰特指数 (ARI) 是这里的标准衡量标准。
您实际上并没有计算对数,但是可以使用二项式简单地计算集合中的对数,只需(n*(n-1))>>2
.
每个集群和每个集群交集都需要这个。
聚合了所有交集的结果,很容易看出这对于簇的排列(以及因此对于簇标签)是不变的。兰德指数是预测两个对象a,b是在同一个簇中,还是在不同簇中的准确率。 ARI 通过调整机会改进了这一点:在一个非常不平衡的问题中,随机结果可以获得很高的准确性,但在 ARI 中它平均接近于 0。
使用兰德指数:
import numpy as np
from scipy.special import comb
def rand_index_score(clusters, classes):
tp_plus_fp = comb(np.bincount(clusters), 2).sum()
tp_plus_fn = comb(np.bincount(classes), 2).sum()
A = np.c_[(clusters, classes)]
tp = sum(comb(np.bincount(A[A[:, 0] == i, 1]), 2).sum()
for i in set(clusters))
fp = tp_plus_fp - tp
fn = tp_plus_fn - tp
tn = comb(len(A), 2) - tp - fp - fn
return (tp + tn) / (tp + fp + fn + tn)
clusters = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
classes = [0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 0, 2, 2, 2, 0]
rand_index_score(clusters, classes)
0.6764705882352942
假设我有两个如下所示的聚类结果:
clustering = [[8, 9, 10, 11], [14, 13, 4, 7, 6, 12, 5, 15], [1, 2, 0, 3]]
correct_clustering = [[2, 8, 10, 0, 15], [12, 13, 9, 14], [11, 3, 5, 1, 4, 6, 7]]
我将如何比较 clustering
中包含的结果与 correct_clustering
中包含的结果。我想要一个介于 0 和 1 之间的数字。我正在考虑计算在同一簇中正确聚集在一起的对的分数。但是想不出一个程序化的方法来解决这个问题。
您可以在sklearn
中使用函数adjusted_rand_score
:
from sklearn.metrics import adjusted_rand_score
clustering = sorted((i, num) for num, lst in enumerate(clustering) for i in lst)
clustering = [i for _, i in clustering]
# [2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]
correct_clustering = sorted((i, num) for num, lst in enumerate(correct_clustering) for i in lst)
correct_clustering = [i for _, i in correct_clustering]
# [0, 2, 0, 2, 2, 2, 2, 2, 0, 1, 0, 2, 1, 1, 1, 0]
ari = adjusted_rand_score(correct_clustering, clustering)
# -0.012738853503184737
函数 returns 的值介于 1 和 -1 之间,因此要获得介于 0 和 1 之间的值,您需要重新缩放:
ari_scaled = (ari + 1) / 2
# 0.49363057324840764
最佳实践措施确实基于配对计数。
特别是调整后的兰特指数 (ARI) 是这里的标准衡量标准。
您实际上并没有计算对数,但是可以使用二项式简单地计算集合中的对数,只需(n*(n-1))>>2
.
每个集群和每个集群交集都需要这个。
聚合了所有交集的结果,很容易看出这对于簇的排列(以及因此对于簇标签)是不变的。兰德指数是预测两个对象a,b是在同一个簇中,还是在不同簇中的准确率。 ARI 通过调整机会改进了这一点:在一个非常不平衡的问题中,随机结果可以获得很高的准确性,但在 ARI 中它平均接近于 0。
使用兰德指数:
import numpy as np
from scipy.special import comb
def rand_index_score(clusters, classes):
tp_plus_fp = comb(np.bincount(clusters), 2).sum()
tp_plus_fn = comb(np.bincount(classes), 2).sum()
A = np.c_[(clusters, classes)]
tp = sum(comb(np.bincount(A[A[:, 0] == i, 1]), 2).sum()
for i in set(clusters))
fp = tp_plus_fp - tp
fn = tp_plus_fn - tp
tn = comb(len(A), 2) - tp - fp - fn
return (tp + tn) / (tp + fp + fn + tn)
clusters = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
classes = [0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 0, 2, 2, 2, 0]
rand_index_score(clusters, classes)
0.6764705882352942