计算聚类精度
Calculating cluster accuracy
我想写一个python代码来计算聚类精度r
如下:
r = (
A1
+ ... +
Ai
+ ...
Ak
) / (the number of data objects)
其中 Ai
是第 i 个集群及其对应的真实集群中出现的数据对象的数量。
我需要实现它,以便将聚类性能与使用此准确性标准的研究论文进行比较。
我在sklearn中搜索了现有的方法,但找不到这样做的方法并尝试自己编写。
这是我写的代码:
# For each label in prediction, extract true labels of the same
# index as 'labels'. Then count the number of instances of respective
# true labels in 'labels', and assume the one with the maximum
# number of instances is the corresponding true label.
pred_to_true_conversion={}
for p in np.unique(pred):
labels=true[pred==p]
unique, counts=np.unique(labels, return_counts=True)
label_count=dict(zip(unique, counts))
pred_to_true_conversion[p]=max(label_count, key=label_count.get)
# count the number of instances whose true label is the same
# as the converted predicted label.
count=0
for t, p in zip(true, pred):
if t==pred_to_true_conversion[p]: count+=1
return count/len(true)
但是,我不认为我的"label remapping"方法是一个聪明的方法,应该有更好的方法来计算r
。我的方法有如下问题:
- 它依赖于一个假设,即相应的真实标签是在预测的聚类中出现最频繁的标签,但情况并非总是如此。
- 不同的预测聚类标签与同一个真实聚类标签相关,尤其是当真实标签和预测标签中类个数不同时
如何实现 r
的准确性?或者在任何现有的集群库中是否有方法可以做到这一点?
我相信你所描述的是我前阵子也想做的事情。我是这样解决的:
from sklearn.metrics.cluster import contingency_matrix
from sklearn.preprocessing import normalize
normalize(contingency_matrix(labels_pred=pred, labels_true=true), norm='l1', axis=1)
此矩阵给出了每个 cluster/label 组合的召回率。
编辑:
我认为你用这种方法提出的问题是它固有的。出于某种原因,一些论文更喜欢报告聚类结果的准确性或 F 度量,即使它们不太适合它。This 论文使用不同的方法来计算聚类结果的 F 度量,这至少解决了多个集群被映射到一个真值标签问题。他们使用任务分配算法来解决这个特定问题。
这是我的 'Hungarian F1' 得分代码:
from munkres import Munkres
def f_matrix(labels_pred, labels_true):
# Calculate F1 matrix
cont_mat = contingency_matrix(labels_pred=labels_pred, labels_true=labels_true)
precision = normalize(cont_mat, norm='l1', axis=0)
recall = normalize(cont_mat, norm='l1', axis=1)
som = precision + recall
f1 = np.round(np.divide((2 * recall * precision), som, out=np.zeros_like(som), where=som!=0), 3)
return f1
def f1_hungarian(f1):
m = Munkres()
inverse = 1 - f1
indices = m.compute(inverse.tolist())
fscore = sum([f1[i] for i in indices])/len(indices)
return fscore
f1_hungarian(f_matrix(pred, true))
我想写一个python代码来计算聚类精度r
如下:
r = (
A1
+ ... +
Ai
+ ...
Ak
) / (the number of data objects)
其中 Ai
是第 i 个集群及其对应的真实集群中出现的数据对象的数量。
我需要实现它,以便将聚类性能与使用此准确性标准的研究论文进行比较。
我在sklearn中搜索了现有的方法,但找不到这样做的方法并尝试自己编写。
这是我写的代码:
# For each label in prediction, extract true labels of the same
# index as 'labels'. Then count the number of instances of respective
# true labels in 'labels', and assume the one with the maximum
# number of instances is the corresponding true label.
pred_to_true_conversion={}
for p in np.unique(pred):
labels=true[pred==p]
unique, counts=np.unique(labels, return_counts=True)
label_count=dict(zip(unique, counts))
pred_to_true_conversion[p]=max(label_count, key=label_count.get)
# count the number of instances whose true label is the same
# as the converted predicted label.
count=0
for t, p in zip(true, pred):
if t==pred_to_true_conversion[p]: count+=1
return count/len(true)
但是,我不认为我的"label remapping"方法是一个聪明的方法,应该有更好的方法来计算r
。我的方法有如下问题:
- 它依赖于一个假设,即相应的真实标签是在预测的聚类中出现最频繁的标签,但情况并非总是如此。
- 不同的预测聚类标签与同一个真实聚类标签相关,尤其是当真实标签和预测标签中类个数不同时
如何实现 r
的准确性?或者在任何现有的集群库中是否有方法可以做到这一点?
我相信你所描述的是我前阵子也想做的事情。我是这样解决的:
from sklearn.metrics.cluster import contingency_matrix
from sklearn.preprocessing import normalize
normalize(contingency_matrix(labels_pred=pred, labels_true=true), norm='l1', axis=1)
此矩阵给出了每个 cluster/label 组合的召回率。
编辑:
我认为你用这种方法提出的问题是它固有的。出于某种原因,一些论文更喜欢报告聚类结果的准确性或 F 度量,即使它们不太适合它。This 论文使用不同的方法来计算聚类结果的 F 度量,这至少解决了多个集群被映射到一个真值标签问题。他们使用任务分配算法来解决这个特定问题。
这是我的 'Hungarian F1' 得分代码:
from munkres import Munkres
def f_matrix(labels_pred, labels_true):
# Calculate F1 matrix
cont_mat = contingency_matrix(labels_pred=labels_pred, labels_true=labels_true)
precision = normalize(cont_mat, norm='l1', axis=0)
recall = normalize(cont_mat, norm='l1', axis=1)
som = precision + recall
f1 = np.round(np.divide((2 * recall * precision), som, out=np.zeros_like(som), where=som!=0), 3)
return f1
def f1_hungarian(f1):
m = Munkres()
inverse = 1 - f1
indices = m.compute(inverse.tolist())
fscore = sum([f1[i] for i in indices])/len(indices)
return fscore
f1_hungarian(f_matrix(pred, true))