【问题标题】:UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samplesUndefinedMetricWarning:F 分数不明确,在没有预测样本的标签中设置为 0.0
【发布时间】:2017-08-27 00:19:48
【问题描述】:

我收到了这个奇怪的错误:

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。

我也看了here,不知道是不是同一个bug。这个SO post也没有解决办法。

【问题讨论】:

  • y_true中有一些标签,没有出现在y_pred中,因此定义不明确
  • @VivekKumar 我也收到了同样的警告。我有一个平衡的数据集(500+500),这个警告似乎出现在clf = GridSearchCV(SVC(C=2), tuned_parameters, cv=cv, scoring='f1') clf.fit(X_train, y_train) 阶段。很高兴看到导致警告的原因或如何纠正它。

标签: python scikit-learn


【解决方案1】:

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

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

这意味着没有要计算此标签的 F-score,因此这种情况下的 F-score 被认为是 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

警告将消失。

【讨论】:

  • 这是一个很好的答案,但我会提醒您不要选择使用 unique(y_pred) 计算 f1 分数,因为这可能会产生误导性分数。
  • @RobertSim 你能详细说明一下吗?谢谢。
  • @harrypotter0,我认为他的意思是使用unique(y_pred) 作为标准做法,而不了解您在做什么,可能会产生意想不到的后果。这里发生的是根本没有预测到的标签被简单地忽略了。只要你积极决定那是你感兴趣的,没关系。使用这种方法时,我个人总是会打印出未预测的标签(使用答案开头的集合操作),以确保我不会错过这个事实。
  • 我指的是这个问题,因为我遇到了类似的问题。就我而言,当我检查 y_testy_pred 的长度时,它们的长度相同。那么,当每个真实标签都有一个预测标签时,它怎么可能定义不明确呢?
  • @akalanka,尝试使用np.unique(y_pred)np.unique(y_test)。这些可能有不同的长度。您的所有 y 都有预测标签,但并非所有标签都至少预测过一次。
【解决方案2】:

当我训练我的分类模型时,同样的问题也发生在我身上。 导致此问题的原因是警告消息中所说的“在没有预测样本的标签中”,它会在计算 f1-score 时导致零除。 我在阅读sklearn.metrics.f1_score doc时发现了另一种解决方案,有如下注释:

当真阳性 + 假阳性 == 0 时,精度未定义;当真阳性 + 假阴性 == 0 时,召回未定义。在这种情况下,默认情况下,指标将设置为 0,f-score 也是如此,并且会引发 UndefinedMetricWarning。可以使用 zero_division 修改此行为

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

【讨论】:

  • 不确定他们是否只是更改了警告消息。但是当我遇到错误时,它也已经给出了原因:“UndefinedMetricWarning: Precision is ill-defined and be set to 0.0 due to no predict samples.使用zero_division参数来控制这种行为。"
【解决方案3】:

接受的答案已经很好地解释了为什么会出现警告。如果您只是想控制警告,可以使用precision_recall_fscore_support。它提供了一个(半官方)参数warn_for,可用于使警告静音。

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

正如在某些 cmets 中已经提到的,请谨慎使用。

【讨论】:

    【解决方案4】:

    我在这里遇到了同样的错误,但在阅读了@Shovalt 的回答后,我意识到我的测试/训练拆分非常低。我有一个大数据集开始,但已经将其拆分,其中一组非常小。通过扩大样本量,这个警告消失了,我得到了我的 f1 分数。 从此

    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)
    

    到这里

    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
    

    【讨论】:

    • 增加训练数据大小也对我有用。非常感谢。
    【解决方案5】:

    我注意到这个错误在两种情况下会发生,

    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),您仍然会出现此错误。您可以使用混淆矩阵将其可视化。如果分类是多标签的并且你设置了 param: average='weighted'/micro/macro 只要矩阵中的对角线不为 0 就会得到答案

    希望这会有所帮助。

    【讨论】:

      【解决方案6】:

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

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

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

      【讨论】:

      • 您指出回归和分类之间的区别是正确的,但我从问题中y_testy_pred的离散性质得出这是一个分类问题。
      猜你喜欢
      • 2019-09-22
      • 2018-09-25
      • 2021-10-02
      • 2022-01-09
      • 2018-08-05
      • 2020-07-27
      • 2016-05-15
      • 2019-09-30
      • 2017-02-18
      相关资源
      最近更新 更多