如何计算多标签分类中的 F1 度量?

How to Calculate F1 measure in multi-label classification?

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

"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 个属于多个类别的句子。我用两种方法计算了准确度分数:

If all labels of an example predicted or not?

代码:

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

How many labels are correctly predicted for all examples?

代码:

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 或任何其他库吗?

查看 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 个 类,如果你有 3 个正确预测的 4 个,使用 accuracy_score 将 与正确预测的 40 的预测相同

这是一个错误。

举个例子

>>> 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

我制作了预测标签矩阵 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

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

您可能还想查看 MultiLabelBinarizer,以防您的预测或真实标签在多标签场景中没有固定宽度。这实质上将它们转换为固定长度的零和一数组:

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_]))