Расчет точности, отзыва и F-балла за один проход-python

точность, точность, отзыв и f-оценка измерения качества системы в системах машинного обучения. Это зависит от матрицы путаницы истинных/ложных положительных / отрицательных.

учитывая задачу двоичной классификации, я попытался получить функцию, которая возвращает точность, точность, отзыв и 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 Позитивы / Негативы.

и try-excepts чтобы поймать ZeroDivisionError - это немного лишнее.

Итак, каков питонический способ получить количество истинных/ложных положительных / отрицательных значений без нескольких циклов через набор данных?

как я могу pythonically поймать ZeroDivisionError без нескольких попыток-исключение?


Я также мог бы сделать следующее, Чтобы подсчитать истинные/ложные положительные / отрицательные значения в одном цикле но!--17-->есть ли альтернативный способ без нескольких 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 ответов


каков питонический способ получить количество истинного / ложного Положительные / отрицательные значения без нескольких циклов через набор данных?

Я бы использовал collections.Counter, примерно то, что вы делаете со всеми ifs (Вы должны использовать elifs, поскольку ваши условия являются взаимоисключающими) в конце:

counts = Counter(zip(predicted, gold))

тогда, например,true_pos = counts[1, 1].

как я могу pythonically поймать ZeroDivisionError без множество попробовать-исключение?

для начала, вы должны (почти) никогда не используйте голыми except:. Если вы ловите ZeroDivisionErrors, тогда напишите except ZeroDivisionError. Вы также можете рассмотреть "семь раз отмерь" подход, проверяя, является ли знаменатель 0 перед попыткой разделения, например

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

в зависимости от ваших потребностей, есть несколько библиотек, которые будут вычислять точность, полнота, F-оценка и т. д. Один, который я использовал, это scikit-learn. Предполагая, что вы выровняли lists фактических и прогнозируемых значений, то это так же просто, как...

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 экземпляров timeit на моем ПК дает 0.036 для вашего метода и 0.017 с использованием bitarray при 1000 проходах. Для 1000 экземпляров он переходит к 0.291 и 0.093. За 10000, 3.177 и 0.863. Вы поняли идею.

он довольно хорошо масштабируется, не используя циклов и не имеет для хранения большого промежуточного представления строим временный список кортежей в zip.