UndefinedMetricWarning:F得分定义不明确,在没有预测样本的标签中设置为0.0


77

我收到这个奇怪的错误:

classification.py:1113: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.
'precision', 'predicted', average, warn_for)`

但是在我第一次运行时,它也会打印f分数:

metrics.f1_score(y_test, y_pred, average='weighted')

我第二次跑步,它提供的分数没有错误。这是为什么?

>>> y_pred = test.predict(X_test)
>>> y_test
array([ 1, 10, 35,  9,  7, 29, 26,  3,  8, 23, 39, 11, 20,  2,  5, 23, 28,
       30, 32, 18,  5, 34,  4, 25, 12, 24, 13, 21, 38, 19, 33, 33, 16, 20,
       18, 27, 39, 20, 37, 17, 31, 29, 36,  7,  6, 24, 37, 22, 30,  0, 22,
       11, 35, 30, 31, 14, 32, 21, 34, 38,  5, 11, 10,  6,  1, 14, 12, 36,
       25,  8, 30,  3, 12,  7,  4, 10, 15, 12, 34, 25, 26, 29, 14, 37, 23,
       12, 19, 19,  3,  2, 31, 30, 11,  2, 24, 19, 27, 22, 13,  6, 18, 20,
        6, 34, 33,  2, 37, 17, 30, 24,  2, 36,  9, 36, 19, 33, 35,  0,  4,
        1])
>>> y_pred
array([ 1, 10, 35,  7,  7, 29, 26,  3,  8, 23, 39, 11, 20,  4,  5, 23, 28,
       30, 32, 18,  5, 39,  4, 25,  0, 24, 13, 21, 38, 19, 33, 33, 16, 20,
       18, 27, 39, 20, 37, 17, 31, 29, 36,  7,  6, 24, 37, 22, 30,  0, 22,
       11, 35, 30, 31, 14, 32, 21, 34, 38,  5, 11, 10,  6,  1, 14, 30, 36,
       25,  8, 30,  3, 12,  7,  4, 10, 15, 12,  4, 22, 26, 29, 14, 37, 23,
       12, 19, 19,  3, 25, 31, 30, 11, 25, 24, 19, 27, 22, 13,  6, 18, 20,
        6, 39, 33,  9, 37, 17, 30, 24,  9, 36, 39, 36, 19, 33, 35,  0,  4,
        1])
>>> metrics.f1_score(y_test, y_pred, average='weighted')
C:\Users\Michael\Miniconda3\envs\snowflakes\lib\site-packages\sklearn\metrics\classification.py:1113: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.
  'precision', 'predicted', average, warn_for)
0.87282051282051276
>>> metrics.f1_score(y_test, y_pred, average='weighted')
0.87282051282051276
>>> metrics.f1_score(y_test, y_pred, average='weighted')
0.87282051282051276

另外,为什么会有尾随'precision', 'predicted', average, warn_for)错误消息?没有开放的括号,为什么它以封闭的括号结尾?我在Windows 10的conda环境中使用Python 3.6.0运行sklearn 0.18.1。

我也在这里看过,不知道是否是同一错误。该SO帖子也没有解决方案。


9
y_true中有一些标签,它们没有出现在y_pred中,因此定义不明确
Vivek Kumar

3
@VivekKumar我也收到同样的警告。我有一个平衡的数据集(500 + 500),此警告似乎在此clf = GridSearchCV(SVC(C=2), tuned_parameters, cv=cv, scoring='f1') clf.fit(X_train, y_train)阶段出现。很高兴看到造成该警告的原因或如何纠正该警告。
salvu

Answers:


109

如注释中所述,y_true中的某些标签未出现在y_pred中。特别是在这种情况下,永远不会预测标签“ 2”:

>>> set(y_test) - set(y_pred)
{2}

这意味着该标签没有要计算的F分数,因此这种情况下的F分数被认为是0.0。由于您要求获得平均分数,因此您必须考虑到计算中包括了0分,这就是scikit-learn向您显示该警告的原因。

这给我带来了您第二次看不到该错误。如前所述,这是一个警告,与python中的错误不同。在大多数环境中,默认行为是仅显示一次特定警告。可以更改此行为:

import warnings
warnings.filterwarnings('always')  # "error", "ignore", "always", "default", "module" or "once"

如果在导入其他模块之前进行了设置,则每次运行代码时都会看到警告。

除了设置之外,没有其他方法可以避免第一次看到此警告warnings.filterwarnings('ignore')。你有什么可以做的,就是决定你是不是在没有预测标签的分数感兴趣,然后明确指定标签兴趣(其中至少有一次是预测标签):

>>> metrics.f1_score(y_test, y_pred, average='weighted', labels=np.unique(y_pred))
0.91076923076923078

在这种情况下,不会显示警告。


2
这是一个很好的答案,但我会提醒您不要选择使用计算f1得分,unique(y_pred)因为这可能会产生误导性得分。
罗伯特·辛

@RobertSim您可以对此详细说明吗?谢谢。
Akash Kandpal,

4
@ harrypotter0,我认为他的意思是在unique(y_pred)不了解您正在做的事情的情况下将其用作标准做法可能会带来意想不到的后果。这里发生的是,根本没有预测的标签将被忽略。只要您主动确定自己对这感兴趣,就可以。使用这种方法时,我个人总是会打印出非预期的标签(使用答案开头的设置操作),以确保我不会错过这个事实。
Shovalt

我指的是这个问题,因为我有类似的问题。就我而言,当我检查和的长度时y_testy_pred它们的长度相同。那么,当每个真实标签都具有预测标签时,如何将其定义不正确呢?
akalanka,

3
@akalanka,尝试使用np.unique(y_pred)np.unique(y_test)。这些长度可能不同。您的所有y都有预测的标签,但并非所有标签都至少被预测了一次。
Shovalt

4

根据@Shovalt的回答,但总之:

或者,您可以使用以下代码行

    from sklearn.metrics import f1_score
    metrics.f1_score(y_test, y_pred, labels=np.unique(y_pred))

这将消除警告,并为您提供所需的结果,因为它不再使用唯一模式来考虑这两组之间的差异。


3
这是肖瓦尔特的答案的重复。
诺曼纽斯

3

接受的答案已经很好地说明了警告发生的原因。如果您只想控制警告,可以使用precision_recall_fscore_support。它提供了一个(半官方)参数warn_for,可以用来使警告静音。

(_, _, f1, _) = metrics.precision_recall_fscore_support(y_test, y_pred,
                                                        average='weighted', 
                                                        warn_for=tuple())

如某些评论中已经提到的,请谨慎使用。


1
不,搜索sklearn源,我发现此选项仅适用于precision_recall_fscore_support()
诺曼纽斯

3

当我训练分类模型时,我也遇到了同样的问题。导致此问题的原因是因为警告消息中所说的“在没有谓词的标签中”,在计算f1分数时将导致零除。当我阅读sklearn.metrics.f1_score doc时,我找到了另一个解决方案,注意事项如下:

当真肯定+假肯定== 0时,精度是不确定的;当真阳性+假阴性== 0时,召回率是不确定的。在这种情况下,默认情况下,度量将设置为0,f分数也将设置为0,并且将引发UndefinedMetricWarning。可以使用zero_division修改此行为

zero_division默认值是"warn",你可以将其设置为01要避免UndefinedMetricWarning。它对zero_division我有用;)哦,等等,当我使用sklearn报告时,还有另一个问题,即使用scikit-learn 0.21.3时没有这样的关键字参数。只需通过运行将sklearn更新到最新版本pip install scikit-learn -U


1

如我所见,此错误在两种情况下发生:

  1. 如果已使用train_test_split()拆分数据,则必须确保重置数据的索引(特别是在使用pandas系列对象获取时):y_train,应重置y_test索引。问题是当您尝试使用sklearn.metrics中的得分之一时,例如;precision_score,它将尝试匹配从train_test_split()获得的y_test的改组索引。

因此,请使用np.array(y_test)得分的y_true或y_test.reset_index(drop = True)

  1. 然后,如果您预测的“正值”为0,则仍然会出现此错误,该值用于精度,召回率和f1_scores。您可以使用confusion_matrix将其可视化。如果分类是多标签,并且您设置了param:average ='weighted'/ micro / macro,则只要矩阵中的对角线不为0,您都将得到答案。

希望这可以帮助。


-1

如错误消息所述,用于获取F分数的方法来自sklearn的“分类”部分-因此谈论“标签”。

您有回归问题吗?Sklearn在“功能选择”组下提供了一种用于回归的“ F评分”方法:http ://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.f_regression.html

如果您确实有分类问题,@ Shovalt的回答对我来说似乎是正确的。


您正确地指出了回归和分类之间的区别,但我得出的结论是,由于y_test和的离散性质,这是一个分类问题y_pred
Shovalt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.