在 scikit-learn 中处理不平衡测试集的最佳方法

Posted

技术标签:

【中文标题】在 scikit-learn 中处理不平衡测试集的最佳方法【英文标题】:best way to deal with imbalanced test set in scikit-learn 【发布时间】:2014-05-01 07:16:09 【问题描述】:

是什么?

我的训练数据在两个类别之间按 70/30 划分,而样本外数据可能更像是 90/10。我正在使用随机森林、逻辑回归和梯度提升进行分类并关心概率输出。

【问题讨论】:

如果你关心概率输出,那就不要使用 boosting,its probabilities can be distorted。 【参考方案1】:

如果你使用逻辑回归,你可以尝试以下方法:

    通过将class_weight="auto" 传递给LogisticRegression 构造函数对少数类进行过采样。您可能还想设置intercept_scaling=1e3(或其他一些较大的值)。有关详细信息,请参阅文档字符串。

编辑:根据 sklearn 版本 0.17 'class_weight="balanced"'。

    改变模型的截距。 class_weight 应该确保您获得了 50/50 拆分的截距(之前的对数赔率),对于 90/10 拆分,可以将其转换为一个

    prior = .9
    lr.intercept_ += np.log(prior / (1 - prior)) - np.log((1 - prior) / prior)
    

这种数学技巧在流行病学中很常见(或者我被告知),通常你有一组n_positive 病例和非常小的先验概率,但得到一个实际大小的对照组@987654327 @ 太贵了。

通过将先验乘以它们的输出,而不是直接将其折叠到模型中,其他概率模型也可以发挥类似的技巧。朴素贝叶斯(不是一个好的概率模型,但我还是会提到它)实际上需要一个可选的 class_prior 参数。

【讨论】:

【参考方案2】:

scikit-learn 包有一些解决类不平衡的问题。 例如,sklearn.model_selection.GridSearchCV 默认具有这种拆分机制:“对于整数/无输入,如果估计器是分类器并且 y 是二进制或多类,则使用 StratifiedKFold”。 “折叠是通过保留每个类别的样本百分比来制作的。” 因此,当您通过 GridSearchCV 进行交叉验证时,每个折叠中的类比例始终与所有数据中的比例相同。 可能这对您有所帮助。

【讨论】:

【参考方案3】:

Trevor Hastie 的书 The Elements of Statistical Learning(免费 PDF!)描述了梯度提升,如果这是您获得概率输出的方法,那么它是该工作的一个很好的参考。与几乎任何 ML 方法一样,您应该查看适当的正则化和收缩以纠正 overfitting and bias。

这里提到的逻辑回归提供了一些纠正样本类别大小的技术。 LR 的一个好处是它在班级规模不平衡的情况下表现得相对较好。如果您正在处理大量数据,那么对数线性随机梯度体面的效果非常好。我的一个经验法则是,如果可能的话,我喜欢采用我的想法并对照老式的 LR 或Naive Bayes 进行检查——LR 是关于你可以拥有的最简单的马尔可夫模型,而 NB 是关于你可以拥有的简单贝叶斯网络。通常,经过正确调整的 LR 模型可以很好地扩展,并且可以为您提供您真正想要的。

至于指标,ROC 曲线为您提供排名能力,但不能告诉您您的概率校准得有多好。有一篇名为Bier Curves 的 ICML 论文可以为您提供有关 ROC 曲线的信息以及有关如何校准概率的有意义的数据。或者,如果您想保持简单的图表,例如平衡准确度与预测分数,以查看事情的映射情况,以及 ROC 图表,您可能对数据指标的工作方式有一个很好的了解。

当然,所有这一切的关键问题是数据将您的验证集和建模集分开,等等。良好的数据卫生确实是核心,我认为最重要的是你的问题在。 70/30 与 90/10。我遇到了一个类似的问题,我们的内部语料库有很大的偏见。这实际上可以追溯到你们中的一些人使用专家意见并研究系统在放置真实数据时是否过度拟合,或者是否需要对数据进行一些修复以使其更现实。您更关心 FP 还是覆盖范围?真正回答您的第一个问题归结为您正在尝试做的业务环境:预测、分类、赚钱、做作业。

如果您使用的是概率,您可能需要重新校准您的概率。输出以馈送到另一个 ML 系统我不必担心重新校准,但如果它用于您真正期望概率的地方。输出看起来可能是某种 Beta 曲线校正或等渗回归。

我写了很多,但回答很少。我的老生常谈的答案是从一些优秀的例子中工作,并根据梯度下降(对数线性)例子或 LogisticRegression 类来烘焙你的解决方案。对于您的验证,您需要一个包括概率校准和排名的指标......我会说生成 AUC 和类似于您的样本概率的偏差。至少这是一个开始。研究你的数据,看看你最终是否对自己的方向感到满意。

我希望这会有所帮助。

【讨论】:

【参考方案4】:

对于不平衡的数据集,模型评估应该使用 ROC 曲线下的面积。 sklearn 中的 AUC 分数可以使用metrics.roc_auc_score() 找到。 AUC 有时无法对模型进行正确评估,因此您还应该考虑校准曲线以及 auc 分数(如果需要)。

【讨论】:

以上是关于在 scikit-learn 中处理不平衡测试集的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

机器学习:处理非平衡数据集的办法

scikit-learn 中的不平衡

在机器学习中的不平衡数据集的情况下,AUC 是比准确性更好的指标吗?如果不是,那么哪个是最佳指标?

mllib 如何在内部对不平衡数据集的类进行加权?

不平衡数据集的 Knn 分类器

具有极不平衡数据集的 TensorFlow 分类