Scikit-learn,获取每个类的准确度分数
Posted
技术标签:
【中文标题】Scikit-learn,获取每个类的准确度分数【英文标题】:Scikit-learn, get accuracy scores for each class 【发布时间】:2017-02-07 18:48:45 【问题描述】:是否有内置方法可以分别获取每个班级的准确度分数?我知道在 sklearn 中,我们可以使用metric.accuracy_score
获得整体准确性。有没有办法获得各个班级的准确度分数细分?类似于metrics.classification_report
。
from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
target_names = ['class 0', 'class 1', 'class 2']
classification_report
不给出准确度分数:
print(classification_report(y_true, y_pred, target_names=target_names, digits=4))
Out[9]: precision recall f1-score support
class 0 0.5000 1.0000 0.6667 1
class 1 0.0000 0.0000 0.0000 1
class 2 1.0000 0.6667 0.8000 3
avg / total 0.7000 0.6000 0.6133 5
准确度分数仅给出整体准确度:
accuracy_score(y_true, y_pred)
Out[10]: 0.59999999999999998
【问题讨论】:
【参考方案1】:from sklearn.metrics import confusion_matrix
y_true = [2, 0, 2, 2, 0, 1]
y_pred = [0, 0, 2, 2, 0, 2]
matrix = confusion_matrix(y_true, y_pred)
matrix.diagonal()/matrix.sum(axis=1)
【讨论】:
详细说明,假设列(因此这个答案的“axis = 1”)代表实际类,而行代表预测类,第 i 类的准确度是混淆矩阵的第 ii 个元素第 i 列的总和。数学就是这样计算的。 这个link 很好地解释了混淆矩阵。 我相信这段代码可能不正确。sklearn.metrics.confusion_matrix
将该行作为实际的类。所以我们应该改用axis=0
。
这不就相当于precisio吗?如果你axis=0,你会得到召回吗?【参考方案2】:
你可以使用sklearn的confusion matrix来获取准确率
from sklearn.metrics import confusion_matrix
import numpy as np
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
target_names = ['class 0', 'class 1', 'class 2']
#Get the confusion matrix
cm = confusion_matrix(y_true, y_pred)
#array([[1, 0, 0],
# [1, 0, 0],
# [0, 1, 2]])
#Now the normalize the diagonal entries
cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
#array([[1. , 0. , 0. ],
# [1. , 0. , 0. ],
# [0. , 0.33333333, 0.66666667]])
#The diagonal entries are the accuracies of each class
cm.diagonal()
#array([1. , 0. , 0.66666667])
参考文献
plot Confusion matrix sklearn【讨论】:
计算的不是准确率,而是召回率。 不,在文档中确实如此,它声明 scikit-learn.org/stable/modules/generated/… [1] 混淆矩阵的***条目(***和其他参考资料可能对轴使用不同的约定) 提示:对于 sklearn>=0.22 使用confusion_matrix(..., normalize="true").diagonal()
直接计算每个类的准确率。
@strohne 好像混淆矩阵还不够混淆,不要让它变得更糟:) 上面正确计算了每类准确率,即每类正确分类样本的比率。召回率是正类的每类准确率,不应与整体准确率(所有类的正确预测的比率)混淆。整体准确率可以计算为confusion_matrix(..., normalize="all").diagonal().sum()
。
对于多类分类,每类准确率与每类召回率相同。【参考方案3】:
您可以自己编码:准确率无非是分类良好的样本(真阳性和真阴性)与您拥有的样本总数之间的比率。
然后,对于给定的班级,您无需考虑所有样本,而只考虑您班级的样本。
然后你可以试试这个: 我们先定义一个方便的函数。
def indices(l, val):
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval
上面的函数会返回列表l中某个值val
的索引def class_accuracy(y_pred, y_true, class):
index = indices(l, class)
y_pred, y_true = ypred[index], y_true[index]
tp = [1 for k in range(len(y_pred)) if y_true[k]==y_pred[k]]
tp = np.sum(tp)
return tp/float(len(y_pred))
最后一个函数将返回您寻找的类内准确度。
【讨论】:
我不知道 numpy 中是否有一个现有函数可以返回列表中与您的参数匹配的值的索引。有人有想法吗?非常感谢! 第二个函数使用未定义的“l”。再次分配 y_true 和 y_pred 时还有一种类型。 (但我赞成它,因为它是这里唯一正确的答案)【参考方案4】:我正在添加我的答案,因为我没有在网上找到这个确切问题的任何答案,并且因为我认为我之前建议的其他计算方法是不正确的。
记住准确度定义为:
accuracy = (true_positives + true_negatives) / all_samples
或者说成文字;它是正确分类的示例(正面或负面)的数量与测试集中示例总数之间的比率。
需要注意的重要一点是,对于 TN 和 FN,“否定”与类别无关,意思是“未预测为有问题的特定类别”。例如,考虑以下情况:
y_true = ['cat', 'dog', 'bird', 'bird]
y_pred = ['cat', 'dog', 'cat', 'dog']
这里,第二个“猫”预测和第二个“狗”预测都是假阴性,因为它们不是“鸟”。
你的问题:
据我所知,目前还没有包提供可以满足您要求的方法,但根据准确度的定义,我们可以使用 sklearn 的混淆矩阵方法自行计算。
from sklearn.metrics import confusion_matrix
import numpy as np
# Get the confusion matrix
cm = confusion_matrix(y_true, y_pred)
# We will store the results in a dictionary for easy access later
per_class_accuracies =
# Calculate the accuracy for each one of our classes
for idx, cls in enumerate(classes):
# True negatives are all the samples that are not our current GT class (not the current row)
# and were not predicted as the current class (not the current column)
true_negatives = np.sum(np.delete(np.delete(cm, idx, axis=0), idx, axis=1))
# True positives are all the samples of our current GT class that were predicted as such
true_positives = cm[idx, idx]
# The accuracy for the current class is ratio between correct predictions to all predictions
per_class_accuracies[cls] = (true_positives + true_negatives) / np.sum(cm)
最初的问题是不久前发布的,但这可能会帮助像我这样通过 Google 来到这里的任何人。
【讨论】:
【参考方案5】:你的问题毫无意义。准确度是一个全球性的衡量标准,没有分类准确度之类的东西。根据具体情况,通过真实案例(行)进行标准化的建议会产生所谓的真阳性率、敏感性或召回率。同样,如果您通过预测(列)进行归一化,则称为精度或正预测值。
【讨论】:
是的,我不认为有一种称为“每类”准确性的度量。因为在数学上它没有意义。准确率定义为(TP + TN) / total_population
,问题是如何计算“特定类的总人口”【参考方案6】:
这个问题具有误导性。每个类别的准确度分数等于总体准确度分数。考虑混淆矩阵:
from sklearn.metrics import confusion_matrix
import numpy as np
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
#Get the confusion matrix
cm = confusion_matrix(y_true, y_pred)
print(cm)
这给了你:
[[1 0 0]
[1 0 0]
[0 1 2]]
准确率计算为正确分类的样本占所有样本的比例:
accuracy = (TP + TN) / (P + N)
关于混淆矩阵,分子(TP + TN)是对角线的和。分母是所有单元格的总和。每个班级都一样。
【讨论】:
【参考方案7】:在我看来,准确性是具有不同维度的通用术语,例如精度、召回率、f1 分数(甚至是特异性、灵敏度)等,提供不同角度的准确度度量。因此,函数“classification_report”为每个类输出一系列准确度度量。例如,精度提供了准确检索到的实例(即真阳性)与特定类中可用的实例总数(真阳性和假阴性)的比例。
【讨论】:
嗨,Md Abdul Bari,欢迎来到 Stack Overflow!我完全同意你的回复。尽管它没有回答 CentAu 提出的问题,但不能强调有许多具有不同含义的准确度指标。 我强烈反对。准确性是非常标准化的术语。当然,您可以在不同的上下文中粗略地谈论准确性,但对于分类,它具有非常具体、定义明确的含义。【参考方案8】:这里是解决方案兄弟:
def classwise_accuracy():
a = pd.crosstab(y_test,predict_over)
print(a.max(axis=1)/a.sum(axis=1))
classwise_accuracy()
【讨论】:
以上是关于Scikit-learn,获取每个类的准确度分数的主要内容,如果未能解决你的问题,请参考以下文章
为啥 scikit-learn SVM 分类器交叉验证这么慢?
在 scikit-learn 中获得二元概率分类器的最大准确度
在 scikit-learn 中获取每个亲和传播集群的***术语