【问题标题】:How to Calculate F1 measure in multi-label classification?如何计算多标签分类中的 F1 度量?
【发布时间】:2016-08-05 20:35:56
【问题描述】:

我正在研究句子类别检测问题。例如,每个句子可以属于多个类别:

"It has great sushi and even better service."
True Label:  [[ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  1.]]
Pred Label:  [[ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  1.]]
Correct Prediction!
Output:  ['FOOD#QUALITY' 'SERVICE#GENERAL'] 

我已经实现了一个可以预测多个类别的分类器。我总共有 587 个句子属于多个类别。我通过两种方式计算了准确度分数:

如果一个例子的所有标签都预测到了?

代码:

print "<------------ZERO one ERROR------------>" 
print "Total Examples:",(truePred+falsePred) ,"True Pred:",truePred, "False Pred:", falsePred, "Accuracy:", truePred/(truePred+falsePred)

输出:

<------------ZERO one ERROR------------>
Total Examples: 587 True Pred: 353 False Pred: 234 Accuracy: 0.60136286201

对所有示例正确预测了多少标签?

代码:

print "\n<------------Correct and inccorrect predictions------------>"
print "Total Labels:",len(total[0]),"Predicted Labels:", corrPred, "Accuracy:", corrPred/len(total[0])

输出:

<------------Correct and inccorrect predictions------------> 
Total Labels: 743 Predicted Labels: 522 Accuracy: 0.702557200538

问题: 这些都是通过将预测分数与地面实况标签进行比较来计算的准确度分数。但我也想计算 F1 分数(使用微平均)、精度和召回率。我有基本事实标签,我需要将我的预测与这些基本事实标签相匹配。但是,我不知道如何解决这种类型的多标签分类问题。 我可以在 python 中使用 scikit-learn 或任何其他库吗?

【问题讨论】:

    标签: python machine-learning scikit-learn units-of-measurement multilabel-classification


    【解决方案1】:

    我制作了预测标签矩阵predictedlabel,并且我已经有了正确的类别来比较我在y_test 中的结果。所以,我尝试了以下代码:

    from sklearn.metrics import classification_report
    from sklearn.metrics import f1_score
    from sklearn.metrics import roc_auc_score
    
    print "Classification report: \n", (classification_report(y_test, predictedlabel))
    print "F1 micro averaging:",(f1_score(y_test, predictedlabel, average='micro'))
    print "ROC: ",(roc_auc_score(y_test, predictedlabel))
    

    我得到了以下结果:

            precision    recall  f1-score   support
    
          0       0.74      0.93      0.82        57
          1       0.00      0.00      0.00         3
          2       0.57      0.38      0.46        21
          3       0.75      0.75      0.75        12
          4       0.44      0.68      0.54        22
          5       0.81      0.93      0.87       226
          6       0.57      0.54      0.55        48
          7       0.71      0.38      0.50        13
          8       0.70      0.72      0.71       142
          9       0.33      0.33      0.33        33
         10       0.42      0.52      0.47        21
         11       0.80      0.91      0.85       145
    
         av/total 0.71      0.78      0.74       743
    
     F1 micro averaging: 0.746153846154
     ROC:  0.77407943841
    

    所以,我是这样计算我的结果的!

    【讨论】:

      【解决方案2】:

      查看 sklearn 中已有的 metrics 并了解它们。它们不适用于多类多标签分类,因此您可以自己编写或将类别映射到标签。

      [ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  1.] => 0
      [ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.] => 1
      ...
      

      您必须了解此解决方案的含义:如果一个示例有 4 个类,并且如果您正确预测了 4 个中的 3 个,则使用 accuracy_score 将是相同 作为正确预测的 0 out of 4

      这是一个错误。

      这里是一个例子

      >>> from sklearn.metrics import accuracy_score
      >>> y_pred = [0, 2, 1, 3]
      >>> y_true = [0, 1, 2, 3]
      >>> accuracy_score(y_true, y_pred)
      0.5
      

      【讨论】:

      • 好的,你能告诉我,如果我有一个真实的标签 [0,1,0,1] 和预测的标签 [0,1,1,0]。那么这个例子的准确率和召回率是多少?或者 TN、TP、FN 和 FP 是什么。
      • 如果您按照我之前的建议进行操作,那么您的真实标签将为 0,而您的预测将为 1。因此您的准确率和召回率将为 0。或者您可以更加微妙并为每个类独立计算准确率和召回率,然后平均它们。
      • 因此,对于任何示例 x 真实标签 [0,1,0,1] 和预测标签 [0,1,1,0],我们无法仅通过查看来计算 FP、TP、TN 和 TP 1 和 0 的位置?
      • 请验证我的回答!!!我用下面的方法试了!!!请看答案:) 非常感谢兄弟
      【解决方案3】:

      您可能还想查看MultiLabelBinarizer,以防您的预测或基本事实标签(对于多标签场景)没有恒定的宽度。这实际上将它们转换为一个固定长度的 0 和 1 数组:

      from sklearn.metrics import classification_report
      from sklearn.preprocessing import MultiLabelBinarizer
      
      y_true = [(12, 2, 4, 5),
                (5, 2),
                (12,)
               ]
      
      y_pred = [(4, 5),
                (5, 2),
                (5, 4)
               ]
      
      mlb = MultiLabelBinarizer()
      
      y_true_binarized = mlb.fit_transform(y_true)
      y_pred_binarized = mlb.transform(y_pred)
      
      print(classification_report(y_true_binarized, y_pred_binarized, 
                                  target_names=[str(cls) for cls in mlb.classes_]))
      

      【讨论】:

        猜你喜欢
        • 2018-03-25
        • 2016-01-24
        • 2016-04-07
        • 2020-10-02
        • 2021-09-04
        • 2021-06-28
        • 2017-12-30
        • 2021-08-29
        • 2020-09-25
        相关资源
        最近更新 更多