【问题标题】:sklearn auc ValueError: Only one class present in y_truesklearn auc ValueError:y_true 中只有一个类
【发布时间】:2016-12-25 09:05:03
【问题描述】:

我在 Google 上进行了搜索,并看到了一些有关此错误的 StackOverflow 帖子。他们不是我的案子。

我使用 keras 训练一个简单的神经网络,并对分割后的测试数据集进行一些预测。但是使用roc_auc_score计算AUC时,出现如下错误:

"ValueError: Only one class present in y_true. ROC AUC score is not defined in that case."

我检查了目标标签分布,它们高度不平衡。一些标签(总共 29 个标签)只有 1 个实例。因此,他们很可能在测试标签中没有正面标签实例。所以sklearn的roc_auc_score函数只报告了一类问题。这是合理的。

但我很好奇,当我使用sklearn的cross_val_score函数时,它可以正确处理AUC计算。

my_metric = 'roc_auc' 
scores = cross_validation.cross_val_score(myestimator, data,
                                   labels, cv=5,scoring=my_metric)

不知道cross_val_score发生了什么,是不是因为cross_val_score使用了分层交叉验证数据拆分?


更新
我继续进行一些挖掘,但仍然找不到背后的区别。我看到 cross_val_score 调用check_scoring(estimator, scoring=None, allow_none=False) 返回一个得分手,而check_scoring 将调用get_scorer(scoring) 将返回scorer=SCORERS[scoring]

SCORERS['roc_auc']roc_auc_scorer
roc_auc_scorer

roc_auc_scorer = make_scorer(roc_auc_score, greater_is_better=True,
                                 needs_threshold=True)

所以,它仍在使用 roc_auc_score 函数。我不明白为什么 cross_val_score 与直接调用 roc_auc_score 的行为不同。

【问题讨论】:

  • 什么是my_metric
  • @maxymoo 我使用字符串roc_auc,它是一个有效值。
  • 如果您进行交叉验证并且您的一种标签太少,则某些折叠可能没有任何此类标签。尝试减少折叠次数并确保使用分层抽样。
  • 我遇到了完全相同的问题,我认为问题实际上与 cross_validation 拆分有关! ''' > /usr/local/lib/python2.7/dist-packages/sklearn/model_selection/_validation.py(131)cross_val_score() 129 130 cv = check_cv(cv, y, classifier=is_classifier(estimator)) - -> 131 cv_iter = list(cv.split(X, y, groups)) 产生以下 cv_iter: ipdb> np.count_nonzero(y[cv_iter[0][1],1]) 2 ipdb> np.count_nonzero(y [cv_iter[1][1],1]) 2 ipdb> np.count_nonzero(y[cv_iter[2][1],1]) 0 没有负数 例如第三次拆分

标签: scikit-learn


【解决方案1】:

我认为你的预感是正确的。 AUC(ROC 曲线下的面积)需要足够数量的任一类才能有意义。

默认情况下,cross_val_score 会分别计算每一折的性能指标。另一种选择可能是执行 cross_val_predict 并计算所有折叠组合的 AUC。

你可以这样做:

from sklearn.metrics import roc_auc_score
from sklearn.cross_validation import cross_val_predict
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification


class ProbaEstimator(LogisticRegression):
    """
    This little hack needed, because `cross_val_predict`
    uses `estimator.predict(X)` internally.

    Replace `LogisticRegression` with whatever classifier you like.

    """
    def predict(self, X):
        return super(self.__class__, self).predict_proba(X)[:, 1]


# some example data
X, y = make_classification()

# define your estimator
estimator = ProbaEstimator()

# get predictions
pred = cross_val_predict(estimator, X, y, cv=5)

# compute AUC score
roc_auc_score(y, pred)

【讨论】:

  • 几乎可以肯定你已经解决了你的问题,但是我最近遇到了同样的问题,结果原因很简单:cross_val_score 默认使用 shuffling 交叉验证,它有一个理论上,为 auc 计算提供足够数量的两个类的机会非零。我不知道您使用了哪个拆分器,但它可能类似于 TimeSeriesSplit。根据定义,这 不是 洗牌。从今以后,对于不平衡的数据集,这种拆分可以为某些特定折叠生成同一类的所有实例。
猜你喜欢
  • 2019-11-10
  • 2015-10-17
  • 2018-09-16
  • 2020-11-27
  • 2019-07-25
  • 2015-08-02
  • 1970-01-01
  • 2017-01-03
  • 2016-06-19
相关资源
最近更新 更多