首页 文章

在一次传递中计算精度,召回和F分数 - 蟒蛇

提问于
浏览
10

Accuracy, precision, recall and f-score是机器学习系统中系统质量的度量 . 它取决于真/假阳性/阴性的混淆矩阵 .

鉴于二进制分类任务,我尝试了以下方法来获得一个返回准确性,精确度,召回率和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次以获得真/假阳性/阴性 .

grab ZeroDivisionError 的多重 try-excepts 也有点多余 .

So what is the pythonic way to get the counts of the True/False Positives/Negatives without multiple loops through the dataset?

How do I pythonically catch the ZeroDivisionError without the multiple try-excepts?


我还可以执行以下操作来计算一个循环中的真/假阳性/阴性,但 is there an alternative way without the multiple 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

3 回答

  • 4

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

    我会使用collections.Counter,大致是你在所有的 if (你应该使用 elif ,因为你的条件是相互排斥的)最后做的事情:

    counts = Counter(zip(predicted, gold))
    

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

    如何在没有多个try-excepts的情况下pythonically捕获ZeroDivisionError?

    首先,你应该(几乎)从不使用裸 except: . 如果你正在捕捉 ZeroDivisionError ,那么写 except ZeroDivisionError . 您还可以考虑采用"look before you leap"方法,在尝试除法之前检查分母是否为 0 ,例如

    accuracy = (true_pos + true_neg) / float(len(gold)) if gold else 0
    
  • 11

    这是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 中构建临时元组列表的大型中间表示 .

  • 5

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

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

    使用该库的一个优点是,不同风格的指标(如微观平均,宏观平均,加权,二进制等)都是开箱即用的 .

相关问题