Series · ML Math Derivations · Chapter 9

机器学习数学推导(九):朴素贝叶斯

从贝叶斯定理与条件独立假设出发,完整推导朴素贝叶斯分类器:参数估计、拉普拉斯平滑、三种模型变体,以及为什么这个看似过于简单的模型在实践中如此有效。

引子: 一个训练只需毫秒、特征量级可达百万、几乎没有超参数可调的垃圾邮件过滤器,却能在短文本任务上击败结构复杂得多的模型。朴素贝叶斯靠的就是一个看似离谱的假设——给定类别后所有特征都条件独立——并且毫不掩饰这一点。在几乎所有真实数据上这个假设都不成立,但分类器照样能用。要理解为什么,需要走一趟生成模型、MAP 估计、Dirichlet 先验和偏差-方差权衡的完整链路。本文就把这条路从头走一遍。

你将学到什么

  • 贝叶斯定理作为概率分类的基础,以及贝叶斯最优分类器为什么是其他所有分类器在暗中模仿的目标。
  • 条件独立假设——在几何上付出了什么代价,又在统计上换来了什么。
  • 先验与似然的极大似然估计,以及拉普拉斯平滑背后的 MAP / Dirichlet 视角。
  • 三种主力变体(多项式、伯努利、高斯)以及它们的取舍。
  • 为什么朴素贝叶斯在假设被破坏时仍然能用:Domingos–Pazzani 定理、误差抵消、偏差-方差权衡。
  • 仅依赖 NumPy 的简洁实现,并与 scikit-learn 对照验证。

预备知识

  • 概率论:贝叶斯定理、条件概率、联合分布与边缘分布、高斯密度。
  • 微积分:对数与偏导。
  • 熟悉 第 8 篇:支持向量机 ,特别是判别式建模的视角。

1. 贝叶斯决策论

在加上"朴素"这一刀之前,先要老老实实弄清楚最优概率分类器到底长什么样。朴素贝叶斯只是逼近它的一种具体做法。

1.1 贝叶斯定理:把信念更新写出来

对于类别 $c_k \in \{c_1, \dots, c_K\}$ 和特征向量 $\mathbf{x} \in \mathbb{R}^d$:

$$ P(c_k \mid \mathbf{x}) \;=\; \frac{P(\mathbf{x} \mid c_k)\, P(c_k)}{P(\mathbf{x})}. $$

每一项各司其职:

符号名称直观含义
$P(c_k \mid \mathbf{x})$后验概率看到 $\mathbf{x}$ 之后,类别为 $c_k$ 的可能性
$P(\mathbf{x} \mid c_k)$似然假定类别是 $c_k$,观察到这个 $\mathbf{x}$ 有多合理
$P(c_k)$先验还没看到任何特征前,$c_k$ 出现的频率
$P(\mathbf{x})$证据$\mathbf{x}$ 的边缘概率,纯归一化项

先验为什么重要。 一项 99% 准确率的疾病检测,若实际患病率仅为 $0.1\%$,单次阳性结果只能把后验从 $0.001$ 抬升到约 $0.09$——仍然是十比一倾向于阴性。贝叶斯定理强迫我们把先验的代数运算大声念出来;忽略先验是统计学最经典的错误之一。

1.2 贝叶斯最优分类器

挑选后验概率最大的类别:

$$ \hat{y}(\mathbf{x}) \;=\; \arg\max_{c_k} P(c_k \mid \mathbf{x}) \;=\; \arg\max_{c_k} P(\mathbf{x} \mid c_k)\, P(c_k), $$

其中 $P(\mathbf{x})$ 与 $c_k$ 无关,被约掉。这条规则最小化 0-1 损失:再深的网络、再大的集成模型,期望意义下也无法超过它。剩下的不可消除部分

$$ R^\star(\mathbf{x}) \;=\; 1 - \max_k P(c_k \mid \mathbf{x}) $$

称为贝叶斯风险,其期望 $\mathbb{E}_{\mathbf{x}}[R^\star(\mathbf{x})]$ 是贝叶斯错误率——属于问题本身的不可约噪声。

后续要讨论的所有概率分类器,本质上都是在有限样本下对这条规则的某种近似。

1.3 生成模型 vs 判别模型

逼近 $P(c_k \mid \mathbf{x})$ 有两条路径:

  • 判别模型(逻辑回归、SVM、神经网络)直接学习 $P(y \mid \mathbf{x})$,把全部统计能力压在决策面上,不去管特征如何分布。
  • 生成模型(朴素贝叶斯、LDA、HMM)建模 $P(\mathbf{x}, y) = P(\mathbf{x} \mid y)P(y)$,再通过贝叶斯定理反推后验。
维度判别生成
学习对象$P(y \mid \mathbf{x})$$P(\mathbf{x}, y)$
渐近精度通常更高通常较低
样本效率较低假设成立时更高
处理缺失值困难自然,对缺失维度边缘化即可
能否生成新样本不能
利用无标签数据容易

Ng & Jordan(2001)的经典结果把这种取舍说清楚了:数据无穷多时判别模型胜出,但生成模型收敛得更快。朴素贝叶斯把生成路线推到了极致。


2. 朴素贝叶斯分类器

2.1 为什么必须做一刀切式的简化

要直接估计 $\mathbf{x} \in \{0,1\}^d$ 上的 $P(\mathbf{x} \mid c_k)$,每个类别需要 $2^d - 1$ 个自由参数。词汇表大小 $d = 10{,}000$ 时这彻底不可行。联合分布是真正的瓶颈。

2.2 条件独立假设

朴素贝叶斯一刀斩断这个结:假设给定类别后所有特征条件独立。

$$ P(\mathbf{x} \mid c_k) \;=\; \prod_{j=1}^{d} P\!\left(x^{(j)} \mid c_k\right). $$

可以从两个角度理解:

  1. 因果视角。 把类别看作隐藏的"因",每个特征是独立产生的"果"。一旦确诊为流感,发烧和咳嗽彼此就不再带额外信息。
  2. 统计视角。 每个特征只贡献一个一维条件密度,联合密度就是乘积。参数量从随 $d$ 指数增长降到线性增长

这一假设在几何上的代价如下图所示:左图是真实联合密度(相关、倾斜的等高线),右图是朴素贝叶斯的近似,二者边缘分布完全相同,但联合结构被强行因式分解成了与坐标轴对齐的椭圆。

独立假设:边缘相同,联合不同

两份密度可以差得很远,但——正如 §5 将看到的——分类结果往往差不大。

2.3 分类规则

把贝叶斯定理与条件独立合到一起,并去掉常数 $P(\mathbf{x})$:

$$ \hat{y}(\mathbf{x}) \;=\; \arg\max_{c_k}\; P(c_k) \prod_{j=1}^{d} P\!\left(x^{(j)} \mid c_k\right). $$

$d$ 个小概率连乘很快就会数值下溢。永远在对数空间里算:

$$ \boxed{\;\hat{y}(\mathbf{x}) \;=\; \arg\max_{c_k} \left[\, \ln P(c_k) \;+\; \sum_{j=1}^{d} \ln P\!\left(x^{(j)} \mid c_k\right) \right].\;} $$

整个算法就是这一行。后面要讲的"三种变体"、平滑、概率校准,无非是在讨论如何估计单个 $P(x^{(j)} \mid c_k)$。

下图给出 2D 上两个高斯类的具体形态:

高斯类条件分布与决策边界

每个类拥有一个对角协方差的高斯(即朴素贝叶斯在连续特征下的假设类),决策边界是两类后验相等的等位线——一般是二次曲线,方差相同时退化为直线。

把同样的图换成概率视角,就是后验曲面:

后验热图与一维切片

右图把"软过渡"画了出来:沿一条切线,后验 $P(c_1 \mid \mathbf{x})$ 从 $0$ 平滑升到 $1$,恰好在两条缩放后的似然曲线相交处穿过 $0.5$。那个交点就是决策边界。

2.4 极大似然参数估计

给定训练集 $\mathcal{D} = \{(\mathbf{x}_i, y_i)\}_{i=1}^{N}$,类 $c_k$ 含 $N_k$ 个样本:

类先验(MLE)。 各类样本所占比例:

$$ \hat{P}(c_k) \;=\; \frac{N_k}{N}. $$

离散特征(MLE)。 取值集合 $\{v_1, \dots, v_{S_j}\}$ 上:

$$ \hat{P}\!\left(x^{(j)} = v \mid c_k\right) \;=\; \frac{\#\{i : x_i^{(j)} = v \text{ 且 } y_i = c_k\}}{N_k}. $$

连续特征(高斯假设)。 每个 (特征, 类别) 对单独拟合一个高斯:

$$ P\!\left(x^{(j)} \mid c_k\right) \;=\; \frac{1}{\sqrt{2\pi}\,\sigma_{jk}} \exp\!\left(-\frac{(x^{(j)} - \mu_{jk})^2}{2\sigma_{jk}^2}\right), $$

参数为标准的样本均值与样本方差:

$$ \hat{\mu}_{jk} \;=\; \frac{1}{N_k}\!\sum_{i:\, y_i=c_k}\! x_i^{(j)}, \qquad \hat{\sigma}_{jk}^2 \;=\; \frac{1}{N_k}\!\sum_{i:\, y_i=c_k}\! \bigl(x_i^{(j)} - \hat{\mu}_{jk}\bigr)^2. $$

全部训练就是这些。 没有迭代优化,没有学习率,没有收敛判据。

2.5 拉普拉斯平滑——以及它的贝叶斯灵魂

零计数的灾难。 假设词 excellent 在垃圾邮件训练集中一次都没出现,那么 $\hat{P}(\text{excellent} \mid \text{spam}) = 0$。一旦未来某封邮件中出现了 excellent,就会让 $P(\text{spam} \mid \mathbf{x}) = 0$,无论其他 199 个词有多么"垃圾邮件"。单个词就毁掉了整次分类。

修复方法。 给每个计数加上伪计数 $\alpha > 0$:

$$ \hat{P}\!\left(x^{(j)} = v \mid c_k\right) \;=\; \frac{\#\{i : x_i^{(j)} = v,\, y_i=c_k\} + \alpha}{N_k + \alpha\, S_j}, \qquad \hat{P}(c_k) \;=\; \frac{N_k + \alpha}{N + \alpha K}. $$

$\alpha = 1$ 时称为拉普拉斯(加一)平滑;更小的 $\alpha$ 有时叫 Lidstone 平滑。

为什么这样做有道理。 给多项分布 $P(\cdot \mid c_k)$ 套上对称 Dirichlet 先验 $\mathrm{Dir}(\alpha, \dots, \alpha)$。Dirichlet 是多项分布的共轭先验,所以后验仍是 Dirichlet,参数变成 $\alpha + \text{counts}$。该后验的众数(MAP 估计)正好就是上式。拉普拉斯平滑等价于在均匀 Dirichlet 先验下的 MAP 估计——相当于在看到任何数据之前,每一类已经被"虚拟观察"了 $\alpha$ 次。

可视化如下:

拉普拉斯平滑:消除零概率与向均匀先验收缩

  • 左图:$\alpha$ 增大时,常见词把概率质量让给罕见词和未见词。
  • 右图:每个词的估计被向 $1/V$ 拉拢。常见词被压低,未见词从 $0$ 抬起来。这种"拉力"的强度与 $\alpha / N_k$ 成正比。

$\alpha$ 的选择是一根偏差-方差旋钮:$\alpha$ 小就更相信数据(偏差小、方差大),$\alpha$ 大就更相信均匀先验(偏差大、方差小)。用交叉验证选。


3. 三种变体——同一个贝叶斯规则,不同的似然

分类规则一字不变。变化的只有 $P(x^{(j)} \mid c_k)$ 的建模方式。

三种朴素贝叶斯变体的对比

3.1 多项式朴素贝叶斯——为词频设计

适用于非负整数计数:词频、$n$-gram、哈希桶。

生成故事。 每篇 $c_k$ 类文档相当于从词表分布 $\boldsymbol{\theta}_k = (\theta_{1k}, \dots, \theta_{dk})$(满足 $\sum_j \theta_{jk} = 1$)中独立同分布采词组成的"词袋"。给定词频 $\mathbf{x}$ 的似然为:

$$ P(\mathbf{x} \mid c_k) \;\propto\; \prod_{j=1}^{d} \theta_{jk}^{x^{(j)}}. $$

带平滑的估计量:

$$ \hat{\theta}_{jk} \;=\; \frac{\sum_{i:\, y_i=c_k} x_i^{(j)} + \alpha}{\sum_{j'=1}^{d}\sum_{i:\, y_i=c_k} x_i^{(j')} + \alpha d}. $$

直觉:$c_k$ 类所有词 token 中,恰好是词 $j$ 的比例。

3.2 伯努利朴素贝叶斯——为词的有无设计

适用于二值特征(出现 / 未出现),尤其适合短文本。

生成故事。 词表中每个词独立地抛一枚有偏硬币,正面概率 $p_{jk} = P(x^{(j)} = 1 \mid c_k)$:

$$ P(\mathbf{x} \mid c_k) \;=\; \prod_{j=1}^{d} p_{jk}^{x^{(j)}} (1 - p_{jk})^{1 - x^{(j)}}. $$

与多项式 NB 最关键的差别: 伯努利显式地把每个未出现词的 $(1 - p_{jk})$ 乘进去,缺席本身也是证据。如果某封邮件里没有出现 “free”,而 “free” 通常在 85% 的垃圾邮件中出现,那么这次缺席就是反对垃圾邮件的有力证据。多项式 NB 则会直接忽略未出现的词。

经验法则。 短而稀疏的文档(推文、日志、短查询)通常用伯努利更好;长文档(新闻、评论)通常多项式更优,因为词频本身携带信息。

3.3 高斯朴素贝叶斯——为连续特征设计

适用于实数特征且每类大致单峰:物理量、嵌入向量、传感器数据。

生成故事。 每个类、每个特征都是高斯:

$$ P(x^{(j)} \mid c_k) \;=\; \mathcal{N}\!\left(x^{(j)};\, \mu_{jk},\, \sigma_{jk}^2\right). $$

类条件密度是 $d$ 个一元高斯之积,等价于一个对角协方差的多元高斯。这就是图 1 中那些与坐标轴对齐的椭圆。

一个值得记住的事实:当两类的逐特征方差相同($\sigma_{jk}^2 = \sigma_j^2$ 与 $k$ 无关)时,对数后验比是 $\mathbf{x}$ 的线性函数,高斯 NB 的决策边界与逻辑回归完全一致——只不过参数是用生成式 MLE 估出来的,而非判别式拟合。


4. 实战:垃圾邮件分类

贝叶斯定理、条件独立、拉普拉斯平滑——这三件事在朴素贝叶斯最经典的应用上交汇:垃圾邮件过滤。完整流水线如下:

从词袋到逐类词概率

  1. 分词:把文档切成词。
  2. 构建词频矩阵:行是文档,列是词表,形状 $(N \times d)$。
  3. 估计:从类频率得到 $\hat{P}(c_k)$,从词计数 + 拉普拉斯平滑得到 $\hat{\theta}_{jk}$(多项式)或 $\hat{p}_{jk}$(伯努利)。
  4. 预测:对每个类计算对数得分,取 argmax。

右图展示了估计出的逐类词分布:垃圾邮件把概率质量集中在 “free”、“money”、“win”,正常邮件则集中在 “meeting”、“schedule”、“project”。对一封测试邮件而言,分类就是把每个特征的证据相加:

逐特征对数几率与瀑布图:得到最终决策

从左往右读这张瀑布图:从对数先验比 $\ln \frac{P(\mathrm{spam})}{P(\mathrm{ham})}$ 出发,逐个加入每个词的贡献(正条往上是支持垃圾邮件,负条往下是反对)。最终柱子的高度就是总对数几率,正则判为垃圾邮件。

从这个角度看,朴素贝叶斯的每一次预测,本质上就是一连串"逐特征对数似然比"的求和。


5. 假设错的离谱,为什么还能用?

独立假设几乎从不成立。词彼此共现、症状成簇出现、传感器读数相关。可朴素贝叶斯在文本分类基准上常常击败那些懂得相关性的模型。原因有四,互相加强:

  1. 分类只看排序,不看校准。 argmax 只取决于哪个后验最大,与绝对值无关。一个模型可以概率严重失校,但排序仍然正确。
  2. 取对数后比值中的偏差互相抵消。 算后验之比时,重复的相关特征会把两类的对数似然抬高相近的量,差额中这部分基本对消。
  3. 偏差-方差权衡有利。 独立假设带来一定偏差,但参数量从 $\mathcal{O}(K \cdot d^2)$ 砍到 $\mathcal{O}(K \cdot d)$,方差骤降。在样本量有限时,这笔交易常常划算。
  4. Domingos–Pazzani 定理(1997)。 一个形式化结论:只要朴素贝叶斯估计出的后验排序与真实后验一致,它就是 0-1 损失下最优的——这个条件远弱于独立假设本身的成立。换言之,朴素贝叶斯可以在概率大小上一塌糊涂,却在每一次决策上正确。

这并不意味着不需要诊断。朴素贝叶斯输出的概率不可信任(详见 Q&A)。但只要任务是排序或 argmax,它的实际战斗力远超体量。


6. 参考实现

仅依赖 NumPy 的简洁实现,三种变体齐备。高斯版本在末尾与 scikit-learn 对照验证。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import numpy as np
from collections import defaultdict


class GaussianNB:
    """连续特征:高斯朴素贝叶斯。"""

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        self.prior_ = np.array([(y == c).mean() for c in self.classes_])
        # mu, var: 形状 (K, d)
        self.mu_ = np.array([X[y == c].mean(axis=0) for c in self.classes_])
        self.var_ = np.array([X[y == c].var(axis=0) for c in self.classes_]) + 1e-9
        return self

    def _log_likelihood(self, X):
        # 对每个类把各特征的 log N(x; mu, var) 求和 -> (N, K)
        out = np.empty((X.shape[0], len(self.classes_)))
        for k in range(len(self.classes_)):
            diff2 = (X - self.mu_[k]) ** 2
            ll = -0.5 * (np.log(2 * np.pi * self.var_[k]) + diff2 / self.var_[k])
            out[:, k] = ll.sum(axis=1)
        return out

    def predict_log_proba(self, X):
        log_post = np.log(self.prior_) + self._log_likelihood(X)
        # log-sum-exp 归一化,数值稳定
        log_post -= log_post.max(axis=1, keepdims=True)
        log_post -= np.log(np.exp(log_post).sum(axis=1, keepdims=True))
        return log_post

    def predict(self, X):
        return self.classes_[np.argmax(self.predict_log_proba(X), axis=1)]


class MultinomialNB:
    """词频特征:多项式朴素贝叶斯(带拉普拉斯平滑)。"""

    def __init__(self, alpha=1.0):
        self.alpha = alpha

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        K, d = len(self.classes_), X.shape[1]
        self.prior_ = np.array([(y == c).mean() for c in self.classes_])
        self.log_theta_ = np.empty((K, d))
        for k, c in enumerate(self.classes_):
            counts = X[y == c].sum(axis=0)
            self.log_theta_[k] = np.log((counts + self.alpha) /
                                        (counts.sum() + self.alpha * d))
        return self

    def predict(self, X):
        log_post = np.log(self.prior_) + X @ self.log_theta_.T
        return self.classes_[np.argmax(log_post, axis=1)]


class BernoulliNB:
    """二值特征:伯努利朴素贝叶斯。"""

    def __init__(self, alpha=1.0):
        self.alpha = alpha

    def fit(self, X, y):
        X = (X > 0).astype(float)
        self.classes_ = np.unique(y)
        K, d = len(self.classes_), X.shape[1]
        self.prior_ = np.array([(y == c).mean() for c in self.classes_])
        self.p_ = np.empty((K, d))
        for k, c in enumerate(self.classes_):
            Xc = X[y == c]
            self.p_[k] = (Xc.sum(axis=0) + self.alpha) / (len(Xc) + 2 * self.alpha)
        return self

    def predict(self, X):
        X = (X > 0).astype(float)
        # log P(x|c) = sum [ x log p + (1-x) log (1-p) ]
        log_p = np.log(self.p_)
        log_1mp = np.log(1 - self.p_)
        log_lik = X @ log_p.T + (1 - X) @ log_1mp.T
        log_post = np.log(self.prior_) + log_lik
        return self.classes_[np.argmax(log_post, axis=1)]


# --- 与 scikit-learn 对照 ---
if __name__ == "__main__":
    from sklearn.datasets import load_iris
    from sklearn.model_selection import train_test_split
    from sklearn.naive_bayes import GaussianNB as SkGNB

    X, y = load_iris(return_X_y=True)
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)

    ours = GaussianNB().fit(X_tr, y_tr)
    sk = SkGNB().fit(X_tr, y_tr)

    print(f"自实现:  {(ours.predict(X_te) == y_te).mean():.4f}")
    print(f"sklearn: {sk.score(X_te, y_te):.4f}")
    # 该随机种子下两者均为 0.9778。

7. 习题

习题 1 —— 条件独立的定义

题目。 已知 $P(c_1) = 0.6$,$P(x_1=1 \mid c_1) = 0.8$,$P(x_2=1 \mid c_1) = 0.5$。在朴素贝叶斯假设下计算 $P(x_1=1, x_2=1 \mid c_1)$。

解答。 给定 $c_1$ 后联合分布因式分解:

$$ P(x_1=1, x_2=1 \mid c_1) = P(x_1=1 \mid c_1)\, P(x_2=1 \mid c_1) = 0.8 \times 0.5 = 0.4. $$

$P(c_1)$ 在条件分布内部没有用武之地——只有在求无条件 $P(x_1, x_2)$ 时才会进入计算。

习题 2 —— 数字版的拉普拉斯平滑

题目。 词表大小 $V = 1000$。正类语料共 200 个词 token,其中 excellent 出现 5 次。计算 (a) MLE 估计、(b) 拉普拉斯平滑($\alpha = 1$)估计、(c) 未见词的平滑估计。

解答。

(a) MLE:$\hat{P}(\text{excellent} \mid +) = 5 / 200 = 0.025$。

(b) 平滑:$\hat{P}(\text{excellent} \mid +) = (5+1) / (200 + 1000) = 6 / 1200 = 0.005$。

(c) 未见词:$\hat{P}(w \mid +) = (0+1) / (200 + 1000) = 1/1200 \approx 8.3 \times 10^{-4}$。

注意:当 $\alpha V \gg N_k$(这里 $1000 \gg 200$)时,平滑会把分布压得很平。这正是那根旋钮:类条件数据稀少时,先验占主导。

习题 3 —— 同一封邮件,多项式 vs 伯努利

题目。 一封 100 词邮件中 win 出现 5 次、free 出现 3 次。已知垃圾类下 $P(\text{win} \mid \text{spam}) = 0.05$、$P(\text{free} \mid \text{spam}) = 0.03$(多项式参数);$P(\text{win 出现} \mid \text{spam}) = 0.7$、$P(\text{free 出现} \mid \text{spam}) = 0.6$(伯努利参数)。比较两者的对数似然贡献。

解答。

多项式(依赖词频):

$$ \ln L_{\mathrm{mult}} = 5\ln(0.05) + 3\ln(0.03) = 5(-2.996) + 3(-3.507) = -25.5. $$

伯努利(只看有无):

$$ \ln L_{\mathrm{bern}} = \ln(0.7) + \ln(0.6) = -0.357 + (-0.511) = -0.87. $$

两个数值不能直接对比(背后是不同的概率对象),但形态上很说明问题:多项式让 5 次出现的信号被线性放大,而伯努利把"出现 1 次"和"出现 5 次"压成同一份证据。长文档里这个动态范围是真信息,短文档里通常不是。

习题 4 —— 手算高斯 NB 参数

题目。 $+1$ 类含三个 2D 点:$(1, 2), (2, 3), (3, 1)$。求高斯 NB 参数。

解答。 逐特征 MLE 均值与方差:

$$ \hat\mu_1 = \tfrac{1+2+3}{3} = 2, \quad \hat\sigma_1^2 = \tfrac{(1{-}2)^2 + (2{-}2)^2 + (3{-}2)^2}{3} = \tfrac{2}{3}, $$$$ \hat\mu_2 = \tfrac{2+3+1}{3} = 2, \quad \hat\sigma_2^2 = \tfrac{(2{-}2)^2 + (3{-}2)^2 + (1{-}2)^2}{3} = \tfrac{2}{3}. $$

故 $\hat\sigma_1 = \hat\sigma_2 = \sqrt{2/3} \approx 0.816$。高斯 NB 没有协方差的非对角项——样本 $(1,3)$ 落在"错的对角线"上这件事,根本进不了模型。

习题 5 —— 假设错了为什么还能用

题目。 给出朴素贝叶斯在独立假设被破坏时仍然有效的四条独立理由。

解答。 即 §5 中展开的论证:

  1. 决策只看 argmax:分类需要正确的排序,而非正确的概率绝对值。
  2. 对数比中的偏差抵消:相关特征会把两类的对数似然同时抬高相近的量,在比值中相互抵消。
  3. 偏差-方差权衡有利:用一点偏差换一大块方差降低,在样本量相对 $d$ 偏小时净获利。
  4. Domingos–Pazzani 定理:朴素贝叶斯只要 argmax 与真实后验一致就达到 0-1 损失最优——这个条件远弱于联合分布真的可以分解。

Q&A

为什么叫"朴素"?

“朴素"指的是条件独立这一过于简单的假设——词与词共现、症状成簇出现,但模型偏偏假装它们彼此独立。这个标签强调的就是这种近乎张扬的简化态度。

朴素贝叶斯和逻辑回归的关系?

当各类共享逐特征方差时,高斯 NB 的决策边界是线性的 $\mathbf{w}^\top\mathbf{x} + b = 0$,与逻辑回归形式相同。系数不一样,因为 NB 通过对 $P(\mathbf{x}, y)$ 做生成式 MLE 得到 $\mathbf{w}$,逻辑回归则直接对 $P(y \mid \mathbf{x})$ 做判别式拟合。渐近上逻辑回归不会更差,但 NB 收敛所需样本更少。

朴素贝叶斯输出的概率值可信吗?

不可信。 相关特征的对数似然会被反复累计,所以后验通常过于极端(贴近 0 或 1)。排序任务(argmax、Top-$K$、ROC)不受影响,但若决策依赖概率大小(成本敏感阈值、风险计算),需要在留出集上做 Platt scaling等距回归校准。

时间复杂度?

训练 $\mathcal{O}(Nd)$——对训练集扫一遍。预测 $\mathcal{O}(Kd)$——每个样本一次。没有迭代,没有需要昂贵调参的超参数(顶多 CV 扫一下 $\alpha$)。

缺失特征怎么处理?

天然友好。 当样本 $i$ 的特征 $j$ 缺失,从对数和中省略 $\ln P(x_i^{(j)} \mid c_k)$ 这一项即可。这数学上等价于对缺失维度做边缘化,是生成式建模的真实优势之一。

什么时候应该用朴素贝叶斯?

当 (i) 特征强相关相关结构在不同类之间差异很大(误差抵消失效);(ii) 任务需要校准良好的概率;(iii) 数据充足且判别式模型可行——逻辑回归、梯度提升或 Transformer 通常会胜出。


参考文献

  • Domingos, P., & Pazzani, M. (1997). On the optimality of the simple Bayesian classifier under zero-one loss. Machine Learning, 29(2-3), 103-130.
  • Ng, A. Y., & Jordan, M. I. (2001). On discriminative vs. generative classifiers: A comparison of logistic regression and naive Bayes. NeurIPS.
  • McCallum, A., & Nigam, K. (1998). A comparison of event models for naive Bayes text classification. AAAI Workshop on Learning for Text Categorization.
  • Manning, C. D., Raghavan, P., & Schütze, H. (2008). Introduction to Information Retrieval. Cambridge University Press. Chapter 13.
  • Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer. Section 8.2.
  • Murphy, K. P. (2012). Machine Learning: A Probabilistic Perspective. MIT Press. Chapter 3.

系列导航

主题链接
8支持向量机<– 上一篇
9朴素贝叶斯当前位置
10半朴素贝叶斯与贝叶斯网络下一篇 –>

Liked this piece?

Follow on GitHub for the next one — usually one a week.

GitHub