朴素贝叶斯:不平衡测试数据集

17 投票
3 回答
10833 浏览
提问于 2025-04-18 10:46

我正在使用scikit-learn的多项式朴素贝叶斯分类器来进行二分类文本分类(这个分类器可以告诉我文档是否属于类别X)。我用一个平衡的数据集来训练我的模型,然后用一个平衡的测试集来测试它,结果非常不错。

这个分类器需要实时运行,并且要不断分析随机输入的文档。

但是,当我在实际环境中运行我的分类器时,假阳性的数量非常高,因此我的精确度很低。原因很简单:在实时情况下,分类器遇到的负样本数量要多得多(大约90%的时间),这和我用来测试和训练的理想平衡数据集不符。

有没有办法在训练时模拟这种实时情况,或者有没有什么技巧可以使用(包括对文档进行预处理,以查看它们是否适合分类器)?

我原本打算用一个不平衡的数据集来训练我的分类器,比例和我在实时情况下的比例相同,但我担心这可能会让朴素贝叶斯偏向负类,从而失去我在正类上的召回率。

任何建议都很受欢迎。

3 个回答

2

我觉得gustavodidomenico说得很对。你可以把朴素贝叶斯看作是在学习一种概率分布,这里指的是单词属于不同主题的概率。所以,训练数据的平衡性很重要。如果你使用决策树,比如随机森林模型,你就是在学习一些规则来进行分类(没错,这里也涉及到概率分布,抱歉我说得有点模糊,但有时候直观的理解更有帮助)。在很多情况下,决策树比朴素贝叶斯更稳健,可能就是因为这个原因。

3

正如@Ben Allison所说,你遇到的问题主要是你的分类器准确率不够高,或者更具体地说:它的假阳性率对于它所处理的类别分布来说太高了。

教科书上的解决办法是使用一个平衡的训练集来训练分类器,这样可以得到一个“好”的分类器,然后在分类器的性能曲线(比如ROC曲线)上找到一个最佳点,以平衡你的准确性要求;我猜在你的情况下,可能更倾向于降低假阳性率,同时提高假阴性率。

不过,情况可能是分类器根本不够好,导致在假阳性率合理的情况下,你可能会漏掉太多好的案例。

解决这个问题的一种方法当然是使用更多的数据,或者尝试另一种类型的分类器;比如线性回归、逻辑回归或支持向量机(SVM),这些在文本分类中通常表现不错。

话虽如此,可能你出于某种原因(比如训练时间的限制、频繁添加新类别或已有模型的使用)更喜欢使用朴素贝叶斯。在这种情况下,我可以给出一些实用的建议。

  1. 假设你已经有了构建朴素贝叶斯分类器的工作流程,你可以考虑提升(Boosting)。一般来说,这些方法会训练几个较弱的分类器,最终组合成一个更强的分类器。提升朴素贝叶斯分类器的效果很好,比如可以参考这里。最佳效果通常需要一个规模大且干净的训练集。
  2. 另一个实用且简单的解决方案(虽然看起来不那么“漂亮”)是,在现有分类器后面再加一层简单的二项朴素贝叶斯分类器,并设定一个阈值——本质上是一个“关键词”过滤器,只有包含至少n个来自给定词典的单词的文档才会被标记为正例(你也可以允许某些单词被计算多次)。根据你的问题领域,可能可以手动构建这样的词典。经过一些尝试,我发现这种方法显著改善了假阳性率,同时对假阴性率的影响相对较小。
11

你遇到了一个关于分类的问题,这个问题是因为类别分布不平衡。对于那些认为问题出在朴素贝叶斯方法上的观点,我要表示不同意,我会解释一下,希望能让你明白问题所在。

想象一下,你的假阳性率是0.01,真阳性率是0.9。这意味着你的假阴性率是0.1,真阴性率是0.99。

假设有一个理想的测试场景,你从每个类别中都有100个测试案例。根据预期,你会得到1个假阳性和90个真阳性。太好了!你的正类精确度是90 / (90+1)!

现在假设负类的例子比正类多1000倍。测试中仍然是100个正类例子,但现在有1000000个负类例子。你仍然得到了90个真阳性,但(0.01 * 1000000)= 10000个假阳性。糟糕!你的精确度几乎变成零(90 / (90+10000))。

这里的关键是分类器的性能并没有改变;假阳性和真阳性率保持不变,但类别的平衡发生了变化,导致你的精确度大幅下降。

解决这个问题就比较复杂了。如果你的得分是可分的,但阈值设置错误,你应该查看基于后验概率的ROC曲线,看看是否有合适的阈值能达到你想要的性能。如果你的得分不可分,可以尝试不同的分类器,看看能否找到一个可分的(逻辑回归几乎可以替代朴素贝叶斯;不过你可能还想尝试一些非线性分类器,比如神经网络或非线性支持向量机,因为你可能会得到非线性边界来划分一个非常小的类别)。

为了模拟这种效果,你可以简单地在列联表中将实例数量乘以一个合适的倍数(例如,如果你的负类是正类的10倍,那么在测试中每个负类实例在列联表中加10个计数,而不是1个)。

希望这些信息能帮助你理解你面临的问题。

撰写回答