我正在尝试验证一个对某些数据执行命名实体识别的ML模型。我的问题与F1成绩的计算方式有关。我使用sklearn 的分类报告
print(preds[:2],labels[:2])
#output: [[5, 5, 5, 5, 5, 5, 5, 5, 1],[6, 2]] [[1, 5, 5, 5, 5, 5, 5, 5, 5, 5],[6, 2]]
这里我们有真实的标签Id和预测的Id。正如我们所看到的,第一个标签不同,即在预测中它具有值"0";1〃;,然而在标签中它具有值"0";5〃;。在我看来,这意味着代币被错误地分类了。接下来,为了使用sklearning度量,我们必须使用MultiLabelBinarizer中的fit_transform转换数组,因为我们有两个以上的标签。
transformed_labels = MultiLabelBinarizer().fit_transform(labels)
transformed_preds = MultiLabelBinarizer().fit_transform(preds)
print(transformed_preds [:2],transformed_labels [:2])
#output: [[1 0 0 1 0],[0 1 0 0 1]] [[1 0 0 1 0],[0 1 0 0 1]]
这是我不明白的部分。此方法只保存在每个序列中使用的实体,而不关心标签的任何顺序或数量。
labels = ['Date','Place','Org','Person','Event']
print(classification_report(transformed_labels ,transformed_preds ,target_names=labels))
precision recall f1-score support
Date 0.69 0.92 0.82 122
Place 0.90 0.94 0.93 195
Org 0.76 0.85 0.78 79
Person 0.99 0.98 0.98 434
Event 0.81 0.69 0.73 55
最后,度量值很高,但我认为它们不准确,因为它们只是根据预测序列中每个实体是否至少出现一次来计算的。
我读错了吗?
我看到的另一种方法:
def calc_precision(pred, true):
precision = len([x for x in pred if x in true]) / (len(pred) + 1e-20) # true positives / total pred
return precision
在这里,我们将根据真实列表计算pred列表的精度。
为此,函数仅检查预测标签是否在真实标签列表中。同样,不考虑出现次数和顺序。
计算净入学率中F1成绩的正确方法是什么?
您可以使用f1分数进行验证。除非您正在进行多标签分类,否则您可以直接调用该函数。如果你解释为什么pred中有两个列表,您可以参考此文档https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html
我假设您对数据集使用IOB2标记方案,并考虑此方案继续回答。由于严格的匹配类型和边界在NER中是必不可少的,您可以将预测输出和真实标签调整为列表列表,并使用Seqeval库。
将其与玩具示例一起使用的示例如下:
from seqeval.metrics import f1_score
y_true = [['B-PER', 'I-PER', 'O'], ['O', 'O', 'B-LOC']]
y_pred = [['B-PER', 'O', 'O'], ['O', 'O', 'B-LOC']]
f1_score(y_true, y_pred)
考虑到玩具的例子,f1得分应该是0.5,因为PER实体的边界没有被正确预测,而LOC实体被正确预测。