朴素贝叶斯:用概率做判断
约 14 分钟
这一节讲一个基于概率的分类器。它的假设很「天真」,效果却出奇地好——尤其在文本分类上。
从贝叶斯公式出发
我们想知道:看到这些特征,它属于某一类的概率有多大?
分母对所有类别都一样,比大小时可以扔掉。所以只需比较分子:
问题在于 没法算——特征的所有组合数量爆炸,数据再多也不够估计。
「朴素」假设:特征之间相互独立
假设在给定类别的条件下,各个特征相互独立,那么:
一个联合概率变成了 个单变量概率的乘积,每一个都能从数据里直接数出来。
这个假设几乎总是错的(「免费」和「优惠」在垃圾邮件里明显相关),但模型照样能用。原因是:分类只需要比较哪个类别的分数更高,即使概率估得不准,排序往往仍然正确。
垃圾邮件分类:最经典的应用
判断一封含「免费」「中奖」「点击」的邮件:
每一项都好算:
对「正常邮件」算一遍同样的式子,哪个大就判哪类。
两个必须处理的工程问题
① 零概率问题
如果「区块链」这个词从没在垃圾邮件里出现过,,整个连乘就变成 0——一个词直接否决了所有其他证据。
解决:拉普拉斯平滑(加一平滑),分子加 1,分母加词表大小:
② 下溢问题
几百个小于 1 的概率连乘,结果会小到浮点数表示不了(变成 0)。
解决:取对数,连乘变连加:
对数不改变大小顺序,但数值稳定得多。这是数值计算里的通用技巧,在损失函数、似然估计中反复出现。
三个变体,对应不同数据
| 变体 | 适用 | sklearn |
|---|---|---|
| 多项式 | 词频计数 | MultinomialNB |
| 伯努利 | 词「出现/未出现」的 0-1 特征 | BernoulliNB |
| 高斯 | 连续特征(假设服从正态分布) | GaussianNB |
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import make_pipeline
clf = make_pipeline(CountVectorizer(), MultinomialNB(alpha=1.0)) # alpha 就是平滑系数
它的价值在哪
训练极快(就是数数)、内存极省、小数据也能work、天然支持增量学习。
在深度学习之前,朴素贝叶斯长期是文本分类的标准基线。今天它依然是很好的第一个模型——用来快速判断「这个文本分类问题到底有多难」。
练习:为什么朴素贝叶斯要对概率取对数?如果不取会发生什么?
朴素贝叶斯「朴素」在哪里,这个假设错了为什么还能用?零概率和下溢分别怎么解决?
登录 后可看答案