11

准确度、精确度、召回率和 f 分数是机器学习系统中系统质量的衡量标准。它取决于真/假阳性/阴性的混淆矩阵。

给定一个二元分类任务,我尝试了以下方法来获得一个返回准确率、精度、召回率和 f 分数的函数:

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 次冗余循环以获得真/假阳性/阴性。

try-excepts捕获的倍数ZeroDivisionError也有点多余。

那么在没有通过数据集的多个循环的情况下获取真/假阳性/阴性计数的pythonic方法是什么?

如何在ZeroDivisionError没有多个 try-excepts 的情况下以 Python 方式捕获?


我也可以执行以下操作来计算一个循环中的真/假阳性/阴性,但是有没有没有倍数的替代方法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
4

3 回答 3

13

在没有通过数据集的多个循环的情况下获取真/假阳性/阴性计数的pythonic方法是什么?

最后,我将使用 a collections.Counter,大致是您对所有ifs 所做的事情(您应该使用elifs,因为您的条件是互斥的):

counts = Counter(zip(predicted, gold))

然后例如true_pos = counts[1, 1]

如何在没有多个 try-excepts 的情况下以 Python 方式捕获 ZeroDivisionError?

首先,您应该(几乎)永远不要使用裸except:. 如果你正在捕捉ZeroDivisionErrors,那么写except ZeroDivisionError. 您还可以考虑“先看再跳”0的方法,在尝试除法之前检查分母是否是,例如

accuracy = (true_pos + true_neg) / float(len(gold)) if gold else 0
于 2015-11-13T09:49:09.177 回答
5

这是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 次通过时使用 bitarray 为 0.017。对于 1000 个实例,它达到 0.291 和 0.093。对于 10000、3.177 和 0.863。你明白了。

它可以很好地扩展,不使用循环,并且不必存储大型中间表示,在zip.

于 2015-11-16T17:07:34.217 回答
4

根据您的需要,有几个库可以计算精度、召回率、F 分数等。我使用的一个是scikit-learn. 假设您已经对齐list了实际值和预测值,那么它就像...

from sklearn.metrics import precision_recall_fscore_support as pr
bPrecis, bRecall, bFscore, bSupport = pr(gold, predicted, average='binary')

使用这个库的优点之一是不同风格的度量(如微平均、宏观平均、加权、二进制等)开箱即用。

于 2015-11-16T08:42:47.530 回答