基础 · 09

朴素贝叶斯

条件独立假设明显是错的,但朴素贝叶斯依然好用——因为分类只需要比较大小,不需要概率精确。

12 min read

朴素贝叶斯模型

朴素贝叶斯是一种生成式分类器。它不直接学「给定输入 XX,输出标签 YY 的概率」(那是判别模型),而是反过来——先学「每个类别长什么样」,再用贝叶斯定理翻转过来做预测。

核心公式来自贝叶斯定理

P(Y=ckX)=P(Y=ck)P(XY=ck)P(X)P(Y = c_k \mid X) = \frac{P(Y = c_k) \cdot P(X \mid Y = c_k)}{P(X)}

分类时我们比较所有类别的后验概率,取最大的那个:

y^=argmaxck  P(Y=ck)P(XY=ck)\hat{y} = \arg\max_{c_k} \; P(Y = c_k) \cdot P(X \mid Y = c_k)

分母 P(X)P(X) 对所有类别相同,比较时可以丢掉。现在问题变成了:怎么估计 P(XY=ck)P(X \mid Y = c_k)

生成模型 vs 判别模型:生成模型学联合分布 P(X,Y)P(X, Y)(或等价地学 P(XY)P(X|Y)P(Y)P(Y)),然后用贝叶斯定理推出 P(YX)P(Y|X)。判别模型(如 logistic 回归、SVM)直接学 P(YX)P(Y|X) 或决策边界。生成模型的好处是当数据少时先验能帮忙,且能用来生成数据;缺点是需要对数据分布做假设——如果假设错了,性能会受影响。

条件独立性假设

如果 XX 是一个 nn 维特征向量 X=(X(1),X(2),,X(n))X = (X^{(1)}, X^{(2)}, \ldots, X^{(n)}),直接估计联合条件分布 P(X(1),X(2),,X(n)Y)P(X^{(1)}, X^{(2)}, \ldots, X^{(n)} \mid Y) 需要指数级的参数——根本不可能从有限数据中学到。

朴素贝叶斯做了一个大胆的假设:给定类别 YY 时,所有特征之间相互独立

P(XY=ck)=j=1nP(X(j)Y=ck)P(X \mid Y = c_k) = \prod_{j=1}^{n} P(X^{(j)} \mid Y = c_k)

这就是「朴素」的含义——假设特征之间没有任何关联。这显然是错的(邮件里「免费」和「中奖」经常同时出现),但它把参数量从指数级降到了线性级,使得模型能从少量数据中学习。

于是分类决策变成:

y^=argmaxck  P(Y=ck)j=1nP(X(j)Y=ck)\hat{y} = \arg\max_{c_k} \; P(Y = c_k) \prod_{j=1}^{n} P(X^{(j)} \mid Y = c_k)

为什么错误的假设还能工作? 因为分类只需要比较两个后验概率的大小关系,不需要它们的绝对值精确。只要独立性假设不改变哪个类别赢,分类就是对的。实证表明,即使特征高度相关,朴素贝叶斯的分类准确率通常也不差——虽然输出的概率值本身不可信。

参数估计

模型需要估计两组参数:

先验概率(极大似然估计):

P(Y=ck)=类别 ck 的样本数NP(Y = c_k) = \frac{\text{类别 } c_k \text{ 的样本数}}{N}

条件概率(极大似然估计):

对离散特征,统计频率即可:

P(X(j)=ajlY=ck)=类别 ck 中第 j 个特征取值 ajl 的样本数类别 ck 的样本数P(X^{(j)} = a_{jl} \mid Y = c_k) = \frac{\text{类别 } c_k \text{ 中第 } j \text{ 个特征取值 } a_{jl} \text{ 的样本数}}{\text{类别 } c_k \text{ 的样本数}}

这就是极大似然估计——用频率估计概率。简单直接,但有一个致命问题:如果训练集中某个特征取值在某个类别下从未出现过,条件概率为零,连乘后整个后验直接归零。

拉普拉斯平滑

为了避免零概率问题,用贝叶斯估计(拉普拉斯平滑):

Pλ(X(j)=ajlY=ck)=计数+λ类别 ck 样本数+λSjP_\lambda(X^{(j)} = a_{jl} \mid Y = c_k) = \frac{\text{计数} + \lambda}{\text{类别 } c_k \text{ 样本数} + \lambda \cdot S_j}

其中 SjS_j 是第 jj 个特征的可能取值个数,λ0\lambda \geq 0 是平滑参数。

  • λ=0\lambda = 0:退化为极大似然估计
  • λ=1\lambda = 1:拉普拉斯平滑(最常用)

直觉:给每个计数加一个「虚拟样本」,确保没有概率为零。这等价于对参数施加一个均匀的 Dirichlet 先验——又是贝叶斯的思想。

先验概率同样可以平滑:

Pλ(Y=ck)=Nk+λN+λKP_\lambda(Y = c_k) = \frac{N_k + \lambda}{N + \lambda \cdot K}

文本分类实例

朴素贝叶斯最经典的应用是文本分类——特别是垃圾邮件过滤。

做法:把一封邮件表示为一组词的出现/不出现(词袋模型)。每个词就是一个二值特征。先验是 P(spam)P(\text{spam})P(ham)P(\text{ham}),条件概率是 P(jspam)P(\text{词}_j \mid \text{spam})P(jham)P(\text{词}_j \mid \text{ham})

下面的演示让你体验这个过程——选择邮件中出现的关键词,观察后验概率如何变化:

垃圾邮件分类器 · 朴素贝叶斯

选择邮件中出现的关键词:

条件概率 P(word|class)

免费
0.80
0.05
优惠
0.30
0.90
中奖
0.10
0.99
会议
0.85
0.40
报告
0.90
0.45
spamham

后验概率

P(spam|X)60.4%
P(ham|X)39.6%

分类结果

垃圾邮件

argmax P(Y) · P(免费|Y) · P(!优惠|Y) · P(!中奖|Y) · P(!会议|Y) · P(!报告|Y)

切换关键词,观察后验概率如何随条件独立假设下的连乘而变化。

观察几个现象:

  1. 先验的作用:当没有特别可疑的词时,先验 P(ham)>P(spam)P(\text{ham}) > P(\text{spam}) 会让正常邮件占优。
  2. 一个强特征可以翻盘:「中奖」的 P(中奖spam)=0.9P(\text{中奖}|\text{spam}) = 0.9,一旦出现就大幅拉高垃圾邮件概率。
  3. 连乘效应:多个弱证据可以累积——同时出现「免费」和「优惠」,即使单独看不致命,合在一起就足以判定为垃圾邮件。
  4. 反向证据:「会议」和「报告」是正常邮件的强信号,它们的出现会把概率拉回来。

实际工程中,还需要处理:取对数避免浮点下溢(连乘大量小概率)、选择合适的特征(停用词过滤、TF-IDF 加权)、以及多项式 vs 伯努利两种词袋模型的选择。

这个想法在前沿里