【问题标题】:Why macro F1 measure can't be calculated from macro precision and recall?为什么不能从宏精度和召回率计算宏 F1 度量?
【发布时间】:2021-05-29 05:07:27
【问题描述】:

我有兴趣通过宏精度计算宏 f1 分数并手动召回。但结果并不相同。代码中f1和f1_new最终公式有什么区别?

from sklearn.metrics import precision_score, recall_score, f1_score

y_true = [0, 1, 0, 1, 0 , 1, 1, 0]
y_pred = [0, 1, 0, 0, 1 , 1, 0, 0]

p = precision_score(y_true, y_pred, average='macro')
r = recall_score(y_true, y_pred, average='macro')
f1_new = (2 * p * r) / (p + r) # 0.6291390728476821

f1 = f1_score(y_true, y_pred, average='macro') #  0.6190476190476191

print(f1_new == f1) 
# False

【问题讨论】:

  • 以不同的顺序取平均值并聚合会导致不同的结果。这是关于数学关系的;它属于Cross Validated,不在这里。
  • @AryaMcCarthy 我一直投票赞成关闭 ML 理论/方法问题作为题外话,但这里似乎并非如此。这似乎是一个实现问题(即使是关于 sklearn 内部),具有完全可重现的最小示例,所以我认为它确实属于这里。

标签: machine-learning scikit-learn precision-recall


【解决方案1】:

f1_score 在 scikit-learn 中计算如下:

all_positives = 4
all_negatives = 4
true_positives = 2
true_negatives = 3

true_positive_rate = true_positives/all_positives = 2/4
true_negative_rate = true_negatives/all_negatives = 3/4

pred_positives = 3
pred_negatives = 5

positive_predicted_value = true_positives/pred_positives = 2/3
negative_predicted_value = true_negatives/pred_negatives = 3/5

f1_score_pos = 2 * true_positive_rate * positive_predicted_value / (true_positive_rate + positive_predicted_value)
             = 2 * 2/4 * 2/3 / (2/4 + 2/3)

f1_score_neg = 2 * true_negative_rate * negative_predicted_value / (true_negative_rate + negative_predicted_value)
             = 2 * 3/4 * 3/5 / (3/4 + 3/5)

f1 = average(f1_score_pos, f1_score_neg)
   = 2/4 * 2/3 / (2/4 + 2/3) + 3/4 * 3/5 / (3/4 + 3/5)
   = 0.6190476190476191

这与skicit-learn 的f1_score'macro' 参数的documentation 中给出的定义相匹配:计算每个标签的指标,并找到它们的未加权平均值。此定义也适用于precision_scorerecall_score

您手动计算的 F1 分数如下:

precision = average(positive_predicted_value, negative_predicted_value)
          = average(2/3, 3/5)
          = 19/30

recall = average(true_positive_rate, true_negative_rate)
       = average(2/4, 3/4)
       = 5/8

f1_new = 2 * precision * recall / (precision + recall)
       = 2 * 19/30 * 5/8 / (19/30 + 5/8)
       = 0.6291390728476821

事实上,docs 中的通式F1 = 2 * (precision * recall) / (precision + recall) 只对average='binary'average='micro' 有效,对average='macro'average='weighted' 无效。从这个意义上说,正如它目前在 scikit-learn 中呈现的那样,该公式具有误导性,因为它表明它与所选参数无关,但事实并非如此。

【讨论】:

  • 酷。也许我们应该打开一个问题来指出这一点并要求在文档中添加说明。
猜你喜欢
  • 1970-01-01
  • 2017-06-21
  • 2019-12-07
  • 2012-11-26
  • 2021-09-01
  • 2019-11-16
  • 2023-03-29
  • 2019-09-30
  • 2020-04-16
相关资源
最近更新 更多