一次性计算精度、召回率和 F 分数 - python
Calculating Precision, Recall and F-score in one pass - python
Accuracy, precision, recall and f-score 是机器学习系统中系统质量的度量。它取决于 True/False Positives/Negatives.
的混淆矩阵
给定一个二元分类任务,我尝试了以下方法来获得 returns 准确度、精确度、召回率和 f-score 的函数:
gold = [1] + [0] * 9
predicted = [1] * 10
def evaluation(gold, predicted):
true_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==1)
true_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==0)
false_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==0)
false_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==1)
try:
recall = true_pos / float(true_pos + false_neg)
except:
recall = 0
try:
precision = true_pos / float(true_pos + false_pos)
except:
precision = 0
try:
fscore = 2*precision*recall / (precision + recall)
except:
fscore = 0
try:
accuracy = (true_pos + true_neg) / float(len(gold))
except:
accuracy = 0
return accuracy, precision, recall, fscore
但似乎我已经冗余地循环遍历数据集 4 次以获得 True/False Positives/Negatives.
还有多个 try-excepts
来捕捉 ZeroDivisionError
有点多余。
那么在没有多次循环遍历数据集的情况下获取 True/False Positives/Negatives 计数的 pythonic 方法是什么?
如何在没有多个 try-excepts 的情况下以 python 方式捕获 ZeroDivisionError
?
我也可以执行以下操作以在一个循环中计算 True/False Positives/Negatives 但是 是否有另一种方法没有多个 if
?:
for p,g in zip(predicted, gold):
if p==1 and g==1:
true_pos+=1
if p==0 and g==0:
true_neg+=1
if p==1 and g==0:
false_pos+=1
if p==0 and g==1:
false_neg+=1
what is the pythonic way to get the counts of the True/False
Positives/Negatives without multiple loops through the dataset?
我会使用 collections.Counter
,大致就是你对所有 if
所做的事情(你应该使用 elif
,因为你的条件是互斥的)最后:
counts = Counter(zip(predicted, gold))
那么例如true_pos = counts[1, 1]
.
How do I pythonically catch the ZeroDivisionError without the multiple
try-excepts?
首先,您应该(几乎)永远不要使用裸机 except:
。如果你正在捕捉 ZeroDivisionError
s,那么写 except ZeroDivisionError
。您还可以考虑 "look before you leap" 方法,在尝试除法之前检查分母是否为 0
,例如
accuracy = (true_pos + true_neg) / float(len(gold)) if gold else 0
根据您的需要,有几个库可以计算精度、召回率、F-score 等。我用过的一个是 scikit-learn
。假设您已对齐 list
的实际值和预测值,那么它就像...
一样简单
from sklearn.metrics import precision_recall_fscore_support as pr
bPrecis, bRecall, bFscore, bSupport = pr(gold, predicted, average='binary')
使用此库的优势之一是开箱即用的不同风格的指标(例如微平均、宏平均、加权、二进制等)。
这是 bitarray 包的一个非常自然的用例。
import bitarray as bt
tp = (bt.bitarray(p) & bt.bitarray(g)).count()
tn = (~bt.bitarray(p) & ~bt.bitarray(g)).count()
fp = (bt.bitarray(p) & ~bt.bitarray(g)).count()
fn = (~bt.bitarray(p) & bt.bitarray(g)).count()
有一些类型转换开销,但在那之后,按位运算要快得多。
对于 100 个实例,我 PC 上的 timeit 为您的方法给出了 0.036,在 1000 遍时使用位数组为 0.017。对于 1000 个实例,它变为 0.291 和 0.093。对于 10000、3.177 和 0.863。你明白了。
它的扩展性很好,不使用循环,并且不必在 zip
中存储构建临时元组列表的大型中间表示。
Accuracy, precision, recall and f-score 是机器学习系统中系统质量的度量。它取决于 True/False Positives/Negatives.
的混淆矩阵给定一个二元分类任务,我尝试了以下方法来获得 returns 准确度、精确度、召回率和 f-score 的函数:
gold = [1] + [0] * 9
predicted = [1] * 10
def evaluation(gold, predicted):
true_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==1)
true_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==0)
false_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==0)
false_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==1)
try:
recall = true_pos / float(true_pos + false_neg)
except:
recall = 0
try:
precision = true_pos / float(true_pos + false_pos)
except:
precision = 0
try:
fscore = 2*precision*recall / (precision + recall)
except:
fscore = 0
try:
accuracy = (true_pos + true_neg) / float(len(gold))
except:
accuracy = 0
return accuracy, precision, recall, fscore
但似乎我已经冗余地循环遍历数据集 4 次以获得 True/False Positives/Negatives.
还有多个 try-excepts
来捕捉 ZeroDivisionError
有点多余。
那么在没有多次循环遍历数据集的情况下获取 True/False Positives/Negatives 计数的 pythonic 方法是什么?
如何在没有多个 try-excepts 的情况下以 python 方式捕获 ZeroDivisionError
?
我也可以执行以下操作以在一个循环中计算 True/False Positives/Negatives 但是 是否有另一种方法没有多个 if
?:
for p,g in zip(predicted, gold):
if p==1 and g==1:
true_pos+=1
if p==0 and g==0:
true_neg+=1
if p==1 and g==0:
false_pos+=1
if p==0 and g==1:
false_neg+=1
what is the pythonic way to get the counts of the True/False Positives/Negatives without multiple loops through the dataset?
我会使用 collections.Counter
,大致就是你对所有 if
所做的事情(你应该使用 elif
,因为你的条件是互斥的)最后:
counts = Counter(zip(predicted, gold))
那么例如true_pos = counts[1, 1]
.
How do I pythonically catch the ZeroDivisionError without the multiple try-excepts?
首先,您应该(几乎)永远不要使用裸机 except:
。如果你正在捕捉 ZeroDivisionError
s,那么写 except ZeroDivisionError
。您还可以考虑 "look before you leap" 方法,在尝试除法之前检查分母是否为 0
,例如
accuracy = (true_pos + true_neg) / float(len(gold)) if gold else 0
根据您的需要,有几个库可以计算精度、召回率、F-score 等。我用过的一个是 scikit-learn
。假设您已对齐 list
的实际值和预测值,那么它就像...
from sklearn.metrics import precision_recall_fscore_support as pr
bPrecis, bRecall, bFscore, bSupport = pr(gold, predicted, average='binary')
使用此库的优势之一是开箱即用的不同风格的指标(例如微平均、宏平均、加权、二进制等)。
这是 bitarray 包的一个非常自然的用例。
import bitarray as bt
tp = (bt.bitarray(p) & bt.bitarray(g)).count()
tn = (~bt.bitarray(p) & ~bt.bitarray(g)).count()
fp = (bt.bitarray(p) & ~bt.bitarray(g)).count()
fn = (~bt.bitarray(p) & bt.bitarray(g)).count()
有一些类型转换开销,但在那之后,按位运算要快得多。
对于 100 个实例,我 PC 上的 timeit 为您的方法给出了 0.036,在 1000 遍时使用位数组为 0.017。对于 1000 个实例,它变为 0.291 和 0.093。对于 10000、3.177 和 0.863。你明白了。
它的扩展性很好,不使用循环,并且不必在 zip
中存储构建临时元组列表的大型中间表示。