我想为一个多分类器计算性能指标,特别是精度,召回率和F分数。
我的课程的独特之处在于,有些预测的标签没有出现在真正的标签集中。
metrics
中的sklearn
模块在处理召回和F分数时无法处理未出现在真实标签集中的预测标签。与其他帖子中的建议相反,提供明确的标签清单似乎无法解决问题。
例如,当您评估数据子集的性能时,可能会发生这种不匹配。例如,在命名实体识别系统中,您已经命名了实体标签(例如"PERSON"
,"ORGANIZATION"
,"LOCATION"
)和一个标签来表示未命名的实体(例如"O"
)。为了进行评估,您通常只对命名实体的性能感兴趣(即,数据集中真正标签不是"O"
的行)。但是,通常情况下,某些预测标签将为"O"
,因此在预测集和真实集中的标签清单之间会产生不匹配。
考虑这个玩具示例。您有一个包含3个类别的多类别分类问题:"a"
,"b"
和"c"
。在真实标签集中,只有"a"
和"b"
出现,但是在其中一种情况下,分类器预测为"c"
。
import pandas as pd
import numpy as np
from sklearn import metrics
from prettytable import PrettyTable
data = pd.DataFrame(np.array([["a", "a"], ["b", "a"], ["b", "b"], ["c", "b"]]),
columns=['pred', 'true'])
> pred true
> 0 a a
> 1 b a
> 2 b b
> 3 c b
混淆矩阵的性能如下:
t = PrettyTable(['', 'a', 'b', 'c'])
t.add_row(['a', 1, 0, 0])
t.add_row(['b', 1, 1, 0])
t.add_row(['b', 0, 1, 0])
print(t)
> +---+---+---+---+
> | | a | b | c |
> +---+---+---+---+
> | a | 1 | 0 | 0 |
> | b | 1 | 1 | 0 |
> | c | 0 | 1 | 0 |
> +---+---+---+---+
根据上述混淆矩阵,预期指标应如下:
PRECISION:
a: 1/1 = 1.0
b: 1/2 = 0.5
c: 0/1 = 0.0
overall => 0.5
RECALL:
a: 1/2 = 0.5
b: 1/2 = 0.5
c: 0/0 = NaN -> 0.0
overall => 0.(3)
请注意,当我在metrics
中调用聚合的sklearn
函数时,我在labels
参数的函数调用list(set(data['pred']))
中明确指定了真正的标签清单,因此它包括所有标签,甚至thouse在真实标签列(此处为"c"
中都看不到)。这是以下文章中建议的解决方案:
还要注意,我想将average
设置为'weighted'
,因为在现实世界中,我的课程通常非常不平衡。
metrics.precision_recall_fscore_support(data['true'],
data['pred'],
average='weighted',
labels=list(set(data['pred'])))[:-1]
我得到警告和以下结果:
# If you call the function more than once,
# it will automatically suppress the warning,
# so if you no longer see the warning, this is probably the reason.
UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples.
'recall', 'true', average, warn_for)
(0.75, 0.5, 0.5833333333333333)
如您所见,精度和召回率与我的计算有所不同。如果您在计算两个指标的平均值时都假设函数不包括"c"
的性能,那么得分很有意义。
很显然,向函数提供真实标签的显式清单并不能消除问题。我该怎么做才能使sklearn
在计算中包括"c"
?