【问题标题】:sklearn jaccard_score giving a wrong resultsklearn jaccard_score 给出错误的结果
【发布时间】:2021-03-23 23:47:44
【问题描述】:

我已使用sklearn.metrics.jaccard_score 从我的 python 模型的二进制分类测试中收集参考分数。它输出如下所示,但是当我手动计算指标时,它会产生另一个值。我在这个函数的使用中误解了“jaccard”的含义吗?还是我用错了? sklearn 函数收集的所有其他指标都返回正确的值。 下面是我的代码,手动测试了 jaccard(在计算器中通过将向量作为集合进行比较得到相同的结果,因为我(不是那么)松了一口气)。

def test(X, y, model):
  predictions = model.predict(X, verbose=1).ravel()
  report = classification_report(y, predictions, target_names=['nao_doentes', 'doentes'])
  confMatrix = confusion_matrix(y, predictions)
  tn, fp, fn, tp = confMatrix.ravel()
  jaccard = jaccard_score(y, predictions) # Se comportando de forma estranha

  print(tn, fp, fn, tp)
  print(predictions)
  print(y)
  print(report)
  print(confMatrix)
  print("Jaccard by function: {}".format(jaccard))
      
  # Note that in binary classification, recall of the positive class is also known as “sensitivity”;
  # recall of the negative class is “specificity”.

  dice = ((2*tp) / ((2*tp) + fp + fn))
  jaccard = ((tp + tn) / ((2*(tp + tn + fn + fp)) - (tp + tn)))
  print(dice)
  print("Jaccard by hand: {}".format(jaccard))

然后跟随输出:

2 0 1 1
[1. 0. 0. 0.]
[1 0 1 0]
              precision    recall  f1-score   support

 nao_doentes       0.67      1.00      0.80         2
     doentes       1.00      0.50      0.67         2

    accuracy                           0.75         4
   macro avg       0.83      0.75      0.73         4
weighted avg       0.83      0.75      0.73         4

[[2 0]
 [1 1]]
Jaccard by function: 0.5
0.6666666666666666
Jaccard by hand: 0.6

作为第二个问题,为什么classification_report 似乎将nao_doentes(未生病,葡萄牙语)设置为 1,而将doentes(生病)设置为 0?不应该反其道而行之吗? nao_doentes 在我的集合中设置为 0,doentes 设置为 1(所以在 y 中)。

【问题讨论】:

    标签: python machine-learning scikit-learn neural-network metrics


    【解决方案1】:

    help page,jaccard分数定义为:

    交集的大小除以两个并集的大小 标签集,

    而且他们只看正面类:

    jaccard_score 可能是一个糟糕的指标,如果没有正面评价 样本或类。如果没有 true 或,则 Jaccard 未定义 预测标签,我们的实现将返回 0 分 警告。

    在你的混淆矩阵中,你有:

    intersection = tp # you have 1
    union = tp+fp # you have 2 
    jaccard = intersection / union
    

    应该给你 1 / (1+1) = 0.5 。

    您的标签是正确的。你可以转换标签,你会看到你得到了相同的混淆矩阵:

    import pandas as pd
    
    labels = pd.Categorical(['nao_doentes','doentes'],categories=['nao_doentes','doentes'])
    prediction = [1 ,0 ,0, 0]
    y = [1 ,0, 1, 0]
    
    pd.crosstab(labels[y],labels[prediction])
    
    col_0   nao_doentes doentes
    row_0       
    nao_doentes 2   0
    doentes     1   1
    

    【讨论】:

      【解决方案2】:

      在您的问题中手动计算的 Jaccard 分数与使用默认 scikit-learn jaccard_score 计算的分数不同,因为您手动使用的公式是计算 微平均 Jaccard分数,而 scikit-learn 版本默认只计算正类(“Doentes”)的分数。

      只是为了看看是怎么回事,我们可以看看使用默认方法的 sklearn jaccard_score 与手动计算相比如何:

      import numpy as np
      from sklearn.metrics import jaccard_score
      y_true = np.array([1, 0, 1, 0])
      y_pred = np.array([1, 0, 0, 0])
      
      tp = 1
      tn = 2
      fp = 0
      fn = 1
      
      jaccard_score(y_true, y_pred)
      #  0.5
      
      # And we can check this by using the definition of the Jaccard score for the positive class:
      
      tp / (tp + fp + fn)
      #  0.5
      

      现在我们来看看微平均的Jaccard分数(这里“微平均”的定义来自scikit-learn documentation

      # scikit-learn:
      
      jaccard_score(y_true, y_pred, average='micro')
      # 0.6
      
      # Definition of micro-averaged ("Calculate metrics globally by counting 
      # the total true positives, false negatives and false positives"). 
      # Here we have to define another set of outcomes but this time with the 
      # original negative class as the positive class:
      
      tp_0 = 2
      fp_0 = 1
      tn_0 = 1
      fn_0 = 0
      
      (tp+tp_0)/(tp+tp_0+fp+fp_0+fn+fn_0)
      # 0.6
      
      # And let's now compare this to the original calculation by hand in the question:
      (tp + tn) / ((2*(tp + tn + fn + fp)) - (tp + tn))
      # 0.6
      

      【讨论】:

        猜你喜欢
        • 2018-11-26
        • 1970-01-01
        • 2014-09-16
        • 2011-11-15
        • 2019-02-06
        • 2014-01-30
        • 2018-08-01
        • 2016-08-30
        • 1970-01-01
        相关资源
        最近更新 更多