【问题标题】:Calculating Precision, Recall and F-score in one pass - python一次性计算精度、召回率和 F 分数 - python
【发布时间】:2016-02-14 20:33:05
【问题描述】:

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

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

另外,多个try-excepts 捕捉ZeroDivisionError 有点多余。

那么在不通过数据集进行多次循环的情况下获取真/假阳性/阴性计数的 Python 方法是什么?

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


我还可以执行以下操作来计算一个循环中的真/假阳性/阴性,但是是否有没有多个 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

【问题讨论】:

    标签: python list machine-learning try-except precision-recall


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        获取真/假计数的pythonic方法是什么 没有通过数据集的多个循环的正面/负面?

        我会在最后使用collections.Counter,大致就是你对所有ifs 所做的(你应该使用elifs,因为你的条件是互斥的):

        counts = Counter(zip(predicted, gold))
        

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

        如何在没有倍数的情况下以 Python 方式捕获 ZeroDivisionError 尝试例外?

        首先,您应该(几乎)永远不要使用裸露的except:。如果您正在捕捉ZeroDivisionErrors,请写except ZeroDivisionError。您还可以考虑使用"look before you leap" 方法,在尝试除法之前检查分母是否为0,例如

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

        【讨论】:

        • 酷!!!!我从来没有想过计算元组来计算精度/召回率。
        • @alvas 我看到你打开了一个赏金,但实际上并没有改变问题;我的回答有问题吗?
        • @jonsharpe,我想看看人们还能想出什么其他解决方案。目前,你有最好的答案,很可能赏金会给你,或者至少答案复选标记会给你=)
        猜你喜欢
        • 2011-11-01
        • 2019-12-14
        • 2013-05-31
        • 2020-09-30
        • 2012-11-26
        • 2019-11-27
        • 1970-01-01
        • 2020-06-22
        • 2014-11-20
        相关资源
        最近更新 更多