朴素贝叶斯(Naive Bayes)是一种简单而强大的技术,你应该在分类问题上进行测试和使用。
它易于理解,效果良好,并且构建模型和进行预测的速度很快。仅凭这些原因,你就应该仔细研究一下该算法。
在最近的一篇博文中,你 学会了如何从头开始用 Python 实现朴素贝叶斯算法。
在这篇文章中,你将学到充分利用朴素贝叶斯算法的技巧和窍门。
通过我的新书《掌握机器学习算法》来启动你的项目,书中包含分步教程和所有示例的Excel 电子表格。

更好的朴素贝叶斯
照片由 Duncan Hull 拍摄,保留部分权利
1. 缺失数据
朴素贝叶斯可以处理缺失数据。
算法在模型构建和预测时都会单独处理属性。
因此,如果一个数据实例的某个属性值缺失,它可以在准备模型时被忽略,并且在计算类值的概率时也被忽略。
2. 使用对数概率
概率通常是小的数值。要计算联合概率,你需要将概率相乘。当你将一个小数乘以另一个小数时,你会得到一个非常小的数。
你可能会在浮点数值的精度方面遇到困难,例如下溢。要避免这个问题,请在对数概率空间中操作(取概率的对数)。
这样做是因为在朴素贝叶斯中进行预测,我们需要知道哪个类具有更大的概率(排序),而不是具体概率是多少。
获取您的免费算法思维导图

方便的机器学习算法思维导图样本。
我创建了一份方便的思维导图,其中包含60多种按类型组织的算法。
下载、打印并使用它。
还可以独家访问机器学习算法电子邮件迷你课程。
3. 使用其他分布
要将朴素贝叶斯用于分类属性,你需要为每个观测值计算一个频率。
要将朴素贝叶斯用于实值属性,你可以使用高斯分布来总结属性的密度。或者,你可以使用另一种能更好描述数据分布的函数形式,例如指数分布。
不要局限于朴素贝叶斯算法示例中使用的分布。选择最能表征你的数据和预测问题的分布。
4. 使用概率进行特征选择
特征选择是选择那些最能表征预测变量的数据属性。
在朴素贝叶斯中,每个属性的概率都是独立地从训练数据集中计算出来的。你可以使用搜索算法来探索不同属性概率的组合,并评估它们在预测输出变量方面的性能。
5. 细分数据
你的数据中是否有明确定义的子集能够很好地响应朴素贝叶斯的概率方法?
识别和分离出易于被朴素贝叶斯这类简单的概率方法处理的细分,可以提高你的性能,并让你专注于问题中更难建模的元素。
探索不同的子集,例如平均情况或非常可能被朴素贝叶斯很好处理的流行案例。
6. 重新计算概率
计算每个属性的概率非常快。
这是朴素贝叶斯的一个优势,意味着你可以随着数据的变化重新计算概率。这可能是每月、每天,甚至每小时。
对于其他算法来说,这可能是不可想象的,但在使用朴素贝叶斯建模时,如果存在一些时间漂移,就应该对其进行测试。
7. 用作生成模型
朴素贝叶斯方法表征了问题,然后可以用于对未见过的数据进行预测。
这种概率表征也可以用来生成问题的实例。
在数值向量的情况下,可以对概率分布进行采样,以创建新的虚构向量。
在文本(朴素贝叶斯的一个非常流行的应用)的情况下,该模型可用于创建虚构的输入文档。
这在你的问题中会有什么用处?
至少,你可以使用生成方法来帮助提供模型已表征内容的上下文。
8. 删除冗余特征
如果数据包含高度相关的特征,朴素贝叶斯的性能可能会下降。
这是因为高度相关的特征在模型中会被投票两次,从而夸大了它们的重要性。
使用相关性矩阵成对评估属性之间的相关性,并删除相关性最高的特征。
但是,在进行此类更改之前和之后,请务必在你的问题上进行测试,并坚持能够带来更好结果的方案。
9. 并行计算概率
每个属性的概率是独立计算的。这是该方法中的独立性假设,也是它之所以得名“朴素”的原因。
你可以利用这个假设,通过并行计算属性概率来进一步加快算法的执行速度。
根据数据集的大小和你的资源,你可以使用不同的 CPU、不同的机器或不同的集群来完成。
10. 所需数据量比你想象的少
朴素贝叶斯不需要大量数据就能表现良好。
它需要足够的数据来理解每个属性与输出变量在孤立状态下的概率关系。
鉴于模型忽略了属性之间的交互作用,我们不需要这些交互作用的例子,因此通常比逻辑回归等其他算法需要的数据量少。
此外,它在较小的样本量下也不太可能过拟合训练数据。
如果你没有太多的训练数据,可以尝试朴素贝叶斯。
11. 零观测值问题
如果属性分布与训练数据集相比存在显著差异,朴素贝叶斯将不可靠。
一个重要的例子是分类属性出现了一个在训练中未曾观测到的值。在这种情况下,模型将分配 0 的概率,并且无法进行预测。
这些情况应被检查并以不同的方式处理。在解决了这些情况(已知答案)之后,应重新计算概率并更新模型。
12. 它仍然有效
关于朴素贝叶斯的一个有趣之处在于,即使独立性假设被违反,并且属性之间存在明显的已知关系,它仍然有效。
重要的是,这也是为什么你需要 对各种算法进行抽样检查 的原因之一,因为结果很可能会让你感到惊讶。
总结
在这篇文章中,你学到了很多关于如何使用朴素贝叶斯算法以及如何从中获得更多。
你有什么关于使用朴素贝叶斯(本文未涵盖)的技巧和窍门吗?请留言。
很棒的文章!非常有信息量。非常感谢。🙂
太棒了!谢谢
对于零观测值问题,你有什么建议吗?我目前正在使用拉普拉斯平滑。
小事。我认为你在第 2 部分中是指“联合”概率(joint probabilities)。
谢谢 Matt,已修复。
Jason博士您好,
非常感谢你为计算环境做出的贡献,
我每天都在关注你的信息。
我对朴素贝叶斯有一个不清楚的地方,我训练和测试算法时使用了相同的数据集,但准确率不是 100%。为什么会这样?
算法是用 Python 实现的,得益于你的帖子,我用 SEER 癌症数据进行了训练,经过仔细准备;然后我用同一个文件进行了测试,调用是分开的,但准确率仍然不是 100%。
谢谢!
好问题,我在这里回答了
https://machinelearning.org.cn/faq/single-faq/why-cant-i-get-100-accuracy-or-zero-error-with-my-model
哦!我差点错过这个,谢天谢地,我现在找到了 🙂
我很高兴你觉得这篇帖子有帮助,Matthew。
感谢你对如何改进朴素贝叶斯的解释,Jason。我读了你关于朴素贝叶斯的帖子,但不太确定使用该算法的缺点。我查找了可能的缺点,例如估计器差、与高度相关的特征一起效果差等,但具有相似均值和标准差的特征是否会导致算法表现不佳?
你好 Joseph,
主要限制在于该算法无法捕捉输入变量的联合分布。也就是说,输入特征与其对输出变量的贡献之间任何有趣且有用的交互作用。这就是所谓的朴素贝叶斯独立性假设。
你可以构造一个数据集,其中需要两个构造变量的联合分布才能做出准确的预测,从而显示朴素贝叶斯失效的地方。
希望这能有所帮助。
抱歉回复晚了。感谢你的解释。确实有帮助。
很高兴听到这个消息 Joseph。
嗨 Jason
在使用朴素贝叶斯进行文本分类时,我遇到了一个问题。
训练集中有 3000 多个样本,测试集中有 750 多个样本。
并且样本应分类到 95 个类别中。最终我得到了 39% 的准确率。
如何提高准确率?增加训练样本?还是减少类别?
谢谢!
有这么多类别,我预计准确率已经没有意义了,Johnson。
可以考虑使用对数损失或 AUC 吗?
谢谢你的回复。
我在谷歌上搜索了一下,有人建议使用所谓的“一对多”方案。
我尝试了,但当类别数量增加时,准确率会迅速下降。
你能举一个对数损失或 AUC 的例子吗?
谢谢!
一对多:你从一个二类分类器开始(A 类和“所有其他”),然后“所有其他”类的结果被返回给算法进行分类为 B 类和“所有其他”,依此类推。
一对多或类似的是模型的结构,而不是性能度量。
如果你使用 Python,那么 sklearn 提供了各种度量指标的实现。
https://scikit-learn.cn/stable/modules/classes.html#sklearn-metrics-metrics
谢谢。
我用 Python,也尝试了度量指标。我将类别数量减少到 30,然后得到了
这个
精确率 召回率 f1分数 支持数
25 0.48 1.00 0.65 372
26 0.00 0.00 0.00 22
27 0.00 0.00 0.00 1
20 0.00 0.00 0.00 4
21 0.00 0.00 0.00 4
22 0.00 0.00 0.00 13
23 0.00 0.00 0.00 60
28 0.00 0.00 0.00 21
29 0.00 0.00 0.00 39
1 0.00 0.00 0.00 7
0 0.00 0.00 0.00 17
3 0.00 0.00 0.00 25
2 0.00 0.00 0.00 15
5 0.00 0.00 0.00 7
4 0.00 0.00 0.00 13
7 0.00 0.00 0.00 2
6 0.00 0.00 0.00 6
9 0.00 0.00 0.00 2
8 0.00 0.00 0.00 31
11 0.00 0.00 0.00 29
10 0.00 0.00 0.00 20
13 0.60 0.60 0.60 5
12 0.00 0.00 0.00 4
15 0.00 0.00 0.00 7
14 0.00 0.00 0.00 11
17 0.00 0.00 0.00 24
16 0.00 0.00 0.00 9
19 0.00 0.00 0.00 15
18 0.00 0.00 0.00 1
平均/总计 0.23 0.48 0.31 786
坚持住!
为什么我的评论总是丢失?
谢谢 Jason。
在朴素贝叶斯中使用对数损失或 AUC?
你能给我举个例子吗?
非常感谢!
我审核评论,每 24 小审核一次。
太棒了,这让结果更准确。感谢您将朴素贝叶斯的所有漏洞集中在一起。
很高兴它有帮助。
起初很难。现在我对朴素贝叶斯有了清晰的认识。你能举一个关于删除冗余特征的实际例子吗?
谢谢你。
请看这篇文章
https://machinelearning.org.cn/an-introduction-to-feature-selection/
你好 Jason 先生
如果我删除一个具有与另一个特征相同值的特征,我需要重新训练模型吗?
是的。
很好,它帮助很大。
谢谢,很高兴听到这个。
你好,
在朴素贝叶斯算法中,用于平滑的 alpha 值范围是多少?为什么我们不能将朴素贝叶斯应用于负值?
Jason博士您好,
我可以在使用对数概率时将对数损失度量应用于朴素贝叶斯模型的性能吗?因为如果我们使用对数概率,它会给出实数值,但对数损失期望的值在 [0,1] 之间。
我不明白,你具体遇到了什么问题?
你好,
模型具有标签 0 和 1 的特征向量。我想使用朴素贝叶斯来预测给定阳性标签(例如 0)的某个特征。如何做到?
我建议使用 sklearn。
https://scikit-learn.cn/stable/modules/classes.html#module-sklearn.naive_bayes
您好,感谢您的精彩文章。
我有一个关于朴素贝叶斯的不相关问题:如何在朴素贝叶斯中预测未知类?例如,只训练了 A、B 和 C 类。要预测的数据具有与 A、B 和 C 不同的类。我们如何计算概率来识别这种情况?
提前感谢
模型拟合后,您可以使用 model.predict()。
也许这会有帮助。
https://machinelearning.org.cn/make-predictions-scikit-learn/
我对数值下溢的评论很感兴趣,所以我生成了一系列平均值为 1%(范围 0% 至 2%)的非零伪随机数,并将乘积与自然对数之和的指数进行了比较。当达到大约 133 个这样的值时,使用 64 位(双精度)浮点数会发生乘积下溢,而对数之和则没有问题。
最小的非零 64 位浮点数约为 2e-308,我的随机值的平均 ln 为 -5.3,ln(2e-308)/5.3 = 133,确实在达到该计数时乘积发生了下溢。
这有助于我们量化这个问题可能发生的时间,以及何时使用对数的 CPU 开销才变得有价值(例如,对于 64 位浮点数,超过 100 多个输入变量;对于 32 位浮点数,只有 16 个输入)。
做得好!
几乎可以说,在建模时使用对数概率是一个黄金法则,并且在对概率取对数时添加一个 epsilon。
非常感谢,我有一个问题,希望得到你的帮助。
我收集了具有多个特征和多个类别的数据,一些特征在类别中是冗余的,并且与其他特征不同。例如,类别 A 的特征值为 [2,2,2],类别 B 的特征值为 [3,3,3],等等。
所以方差应该是 0,高斯朴素贝叶斯算法是如何工作的?
我尝试运行了我的程序,它给了我一个不错的性能,但我不知道为什么。
你可以在这里了解高斯朴素贝叶斯的工作原理。
https://machinelearning.org.cn/classification-as-conditional-probability-and-the-naive-bayes-algorithm/
非常感谢。我读了,它很有用,但仍然没有解决我的问题。
当我在检查我的程序时,我发现默认的标准差是 0 值,但我不知道我对不对。如果您有任何想法,请帮助我..
如果标准差为零,则表明该列只有一个值,可能可以删除。
不,具有不同值但相对于类别是静态的列,它确实给出了高准确率。请问我还有其他问题:1-高斯朴素贝叶斯多分类能否绘制 ROC? 2-可以更改高斯朴素贝叶斯中的 theta 和 epsilon 吗?
我很感谢您的帮助,非常感谢。
不,ROC 是用于二分类(2 类)问题的。
朴素贝叶斯中使用的变量的均值和标准差仅用于实值变量,并根据训练数据集进行估计。
好的 Jason 先生,非常感谢您。
不客气。
如何在 Python 中找到朴素贝叶斯模型中最具贡献的属性。
一如既往,通过测试!尝试改变模型中的一些参数,并观察其性能指标的变化。
对于我们逐个获取输入特征值并希望在获得更多信息时更新预测的问题,可以使用朴素贝叶斯吗?
听起来是可能的!
感谢 Jason 撰写的这篇精彩文章。我有一个挑战。如果每个特征都有不同的指数分布、高斯分布等,我该如何在朴素贝叶斯中处理?
你好 Peter……在这种情况下,考虑深度学习和神经网络可能是有益的。
https://machinelearning.org.cn/binary-classification-tutorial-with-the-keras-deep-learning-library/