跳到主要内容

朴素贝叶斯 —— 数单词猜类别

这一章讲三件事: 一个不拟合任何边界的分类机器怎么干活; 「朴素」朴素在哪、又错在哪;以及一个 0.01 的小补丁怎么救活整个算法。 它是垃圾邮件过滤的鼻祖算法,也是全书唯一一个「看不懂数学也能完全复述其工作方式」的算法。

1. 顶层全景

文本「复映的动作电影名作让人感动」
↓ 预处理:拆词、扔掉顺序 → 词袋 {名作, 电影, 感动}
↓ 变成向量 [1,1,0,0,0,1,0,0,0,0,0] (出现的词标 1)
↓ 两套账本(训练时数好):
│ 账本一:每个类别出现的概率 电影 3/6 · 宇宙 3/6
│ 账本二:各类别下每个词的条件概率 「感动」电影 2/3 · 宇宙 1/3
↓ 预测 = 把用到的概率连乘,哪边大判哪边
输出:电影(胜出)

图说:没有边界、没有损失函数、没有梯度下降——只有两张数出来的表。

朴素贝叶斯常用于自然语言的分类问题,垃圾邮件过滤是它最有名的应用1。它的路数和前面所有算法都不同:基于概率做预测,把数据分给概率值最大的那个标签2

2. 主走查:这条标题是「电影」还是「宇宙」?

原书造了 6 条新闻标题当训练数据:3 条电影类、3 条宇宙类3。要分类的验证数据是一条电影类标题——但假装不知道它的类别:「复映的动作电影名作让人感动」。

第一步:拆成词袋

先把文本拆词(分词:把连续的句子切成一个个单词;原书假定这步已由别的工具做完)、只留名词、扔掉词的先后顺序,得到一个集合——这种表示法叫词袋(Bag of Words,BoW):一袋词,不管顺序4。再按「词出现记 1、没出现记 0」变成向量5:

「复映的动作电影名作让人感动」
→ 提名词:复映、动作、电影、名作、感动
→ 去掉训练数据里没有的「复映」,剩下 动作、电影、名作、感动
→ 对照全部 11 个词的词表:
[名作=1, 电影=1, 华丽=0, 动作=1, 世界=0, 感动=1,
沙尘暴=0, 火星=0, 探测=0, 重新开始=0, VR=0]
→ 向量 [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0]

⚠ 一个疑点要点破:按上面「出现记 1」的规则,「动作」应当是 1;
但原书表 2-14 给出的向量里「动作」一列是 0——照它自己的计数规则
对不上,疑似原书排印勘误。下面照原书的向量走(两取法判「电影」的结论不变:
若把「动作」记 1,电影侧连乘多乘一个 1/3,宇宙侧多乘一个 0.01,
差距反而拉得更开)。

顺序在这一步被扔掉了。「动作电影」和「电影动作」在词袋眼里一模一样——这个牺牲是整个算法的地基,第 4 节会回来算这笔账。

第二步:训练=数两张表

训练阶段没有任何梯度下降,就是数数。朴素贝叶斯学两种概率6:

账本一:每个标签出现的概率(先验)
电影 3/6 = 0.5 宇宙 3/6 = 0.5

账本二:各标签下每个单词出现的条件概率(条件概率:
在「某个条件成立」的前提下算另一个事件的概率,
这里的条件是「这条文本属于某类别」)
「感动」:电影类 2/3 ≈ 0.67 宇宙类 1/3 ≈ 0.33
「名作」:电影类 2/3 宇宙类 0 → 补丁后 0.01
「电影」:电影类 2/3 宇宙类 0 → 补丁后 0.01
(全部数值取自原书表 2-13 与图 2-28;原书给出的
「感动」出现比例正是 2/3 ≈ 67% 对 1/3 ≈ 33%[^7])

「感动」这个词两类都会出现,但在电影类里出现得更勤——条件概率的差异,正是分类的信息来源。只看类别比例的话,两边永远各 50%,什么也判断不了;原书特意先摆出这个死胡同再引入条件概率7

第三步:连乘,比大小

预测时,对每个标签把「标签概率 × 各词的条件概率」连乘,乘积大的获胜8。拿我们的验证向量算(概率值按原书表 2-13 的数据推算,平滑 0.01 取自原书;乘积过程为演示补算):

电影侧:0.5 × P(名作|电影) × P(电影|电影) × P(感动|电影)
× 8 个未出现词的「不出现概率」
= 0.5 × (2/3) × (2/3) × (2/3) × (1−0.01)⁸
≈ 0.5 × 0.296 × 0.923
≈ 0.137

宇宙侧:0.5 × P(名作|宇宙) × P(电影|宇宙) × P(感动|宇宙) × 0.99⁸
= 0.5 × 0.01 × 0.01 × (1/3) × 0.923
≈ 0.0000154

0.137 ≫ 0.0000154 → 判「电影」。

原书用 scikit-learn 的 MultinomialNB 跑同一份数据,输出 array([1]),即电影类——判断正确9。推算与代码结论一致。

3. 平滑:一个 0.01 救活整个算法

注意上面宇宙侧那两个 0.01。「名作」「电影」两个词在宇宙类训练数据里一次都没出现,照实数概率就是 0——而连乘里有一个 0,整个乘积瞬间归零:不管这条文本多像宇宙类,只要碰上一个「宇宙类从没见过的词」,宇宙类的得分就永久锁死在零。训练数据终究只是抽样,换更大的语料(喂给机器的文本集合),这个词没准就出现了。

朴素贝叶斯的补丁叫平滑:该是 0 的地方不填 0,填一个很小的概率值(原书用 0.01)10。这一小步让「没见过」和「不可能」分了家——没见过只是证据弱,不是判死刑。垃圾邮件过滤器天天遇到新词,全靠这个补丁活命。

4. 「朴素」是勋章也是病根

算法名里的「朴素」指那个核心假设:每个单词都是相互独立的,词的顺序与组合一概不看,每个词的概率单独数11

它的好处立竿见影:不用学词与词之间的关系,参数就是两张数出来的表,小数据也能训,快得飞起。它的坏处原书用两个场景讲透:

场景独立假设怎么失灵原书原话的例子
输出的数值本身重要连乘出来的「概率」被独立性假设系统性扭曲不适合降水概率这类预测值本身是概率的任务;概率值重要时,别把朴素贝叶斯的输出直接当概率用12
词义随语境变化同一个词在不同上下文(上下文:一个词前后的那些词语环境)里含义不同,「词单独算」就错了「踢」常见于格斗文本;但出现「踢了球」,主题多半是足球13

要处理上下文,就得换模型——原书明说到此为止,没给替代方案。原书没有给替代方案;本书的 17 个算法里也没有——把顺序和语境捡回来的词向量(把每个词变成一串数、让含义变成长度的技术),属于这本书之后的世界(补充:不在书里,来自通用知识)。

判断(我们的,不是书里的): 朴素贝叶斯今天的最佳位置是「第一版基线」——文本分类任务先跑它拿一个底线分数,再决定要不要上更贵的模型。它的独立假设在多数真实文本上是错的,但「错的假设 + 大量独立证据」常常仍能给出正确的排序(垃圾邮件过滤就是靠这个活到今天)。 如果错,会错在: 若某个任务里类别线索恰恰藏在词序里(「不 好」与「不好」),排序也会错,此时基线会严重低估任务难度——上线前应抽查看错的样本是不是这类。

5. 作者的判断与证据

说法性质依据
「感动」电影类 2/3、宇宙类 1/3书内给出演算数字直接来自训练表14
判「电影」正确书内代码运行结果 array([1])代码输出9
概率为 0 的词要用平滑作者给出的工程补丁,取值 0.01 是约定俗成、非推导书内明说「分配小的概率值 0.01」10
独立假设使学习过程简单作者的设计动机陈述书内陈述11
不适合预测概率本身作者的边界警告,与第 03 章判断块呼应书内注意点12

6. 边界与局限

  • 词袋扔掉了语序:「狗咬人」和「人咬狗」在它眼里是同一袋词。原书没有展开这个例子的严重性,只点了顺序与组合被忽略11
  • 双词搭配(「踢了球」)的问题原书归入「上下文」,但没有给出 n-gram(连续 n 个词一起数)这类常规补法——原书此处留白,补一句:把相邻词组当单个词入袋,是词袋框架内最常见的缓解手段(补充:不在书里,来自通用知识)。
  • 每个词的条件概率都由训练数据直接数出,类别里词特别少时,平滑系数的选择会明显左右结果——0.01 换成 0.1 或 0.001,边界样本的判决可能翻转。
  • 版本提示:示例用 MultinomialNB,输入正是第 2 节那张 0/1 表格9

7. 可带走的

  1. 朴素贝叶斯不拟合边界,它数概率、连乘、比大小;
  2. 文本进模型前先拆成词袋:拆词、留名词、扔顺序,出现记 1;
  3. 训练=数两张表:类别概率 + 类别下每个词的条件概率;
  4. 条件概率的差异就是分类的信息;只有类别比例时什么都判不了;
  5. 平滑(0 处填小值 0.01)把「没见过」和「不可能」分开——没有它,一个新词就能锁死一个类;
  6. 「朴素」= 假装词与词独立:换来速度与小数据可用,输掉语序和语境;
  7. 输出的「概率」不能当真概率用,尤其别拿去做风险计算;
  8. 它是文本分类的第一版基线,也是最容易被低估的对手;
  9. 词义随语境漂移(「踢」格斗、「踢了球」足球)时,这套假设彻底失效,得换模型。

8. 原文地图

主题原书章原文位置
垃圾邮件过滤应用2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:2(搜「垃圾邮件过滤上的应用非」)
按最大概率分类2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:8(搜「分类为概率值最大的标签」)
电影/宇宙训练数据2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:10(搜「虚构的新闻标题」) · text/11-ch02-06-2-6-6.txt:27(搜「那部让人感动的电影名作重映」)
先验各 50%、方法固定2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:49(搜「概率是 3/6 = 50%」)
「感动」2/3 对 1/32.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:72(搜「2/3 ≈ 67%」)
条件概率定义2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:76(搜「叫作条件概率」)
词袋 BoW、提名词、0/1 向量2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:88(搜「BoW(Bag of Words,词袋)」) · text/11-ch02-06-2-6-6.txt:90(搜「忽略名词在文本中的顺序」) · text/11-ch02-06-2-6-6.txt:111(搜「值设为 1,否则设为 0」)
验证数据向量2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:143(搜「预测验证数据」)
两种概率2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:148(搜「以下两种概率」)
平滑 0.012.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:173(搜「叫作平滑」) · text/11-ch02-06-2-6-6.txt:175(搜「真有可能出现」)
连乘比较2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:177(搜「两个概率的乘积」)
独立假设2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:207(搜「每个单词都是独立的」)
MultinomialNB、判电影正确2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:215(搜「MultinomialNB」) · text/11-ch02-06-2-6-6.txt:238(搜「说明这次的判断是正确」)
不适合预测概率本身2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:243(搜「降水概率那种预测值是」) · text/11-ch02-06-2-6-6.txt:248(搜「用作概率」)
「踢」与「踢了球」2.6 算法6:朴素贝叶斯text/11-ch02-06-2-6-6.txt:252(搜「踢了球」) · text/11-ch02-06-2-6-6.txt:255(搜「考虑使用其他模型」)

Footnotes

  1. 出处:「2.6 算法6:朴素贝叶斯」第 2 段(text/11-ch02-06-2-6-6.txt:2,搜「垃圾邮件过滤上的应用非」)。

  2. 出处:「2.6 算法6:朴素贝叶斯」第 8 段(text/11-ch02-06-2-6-6.txt:8,搜「分类为概率值最大的标签」)。

  3. 出处:「2.6 算法6:朴素贝叶斯」第 10 段(text/11-ch02-06-2-6-6.txt:10,搜「虚构的新闻标题」);6 条训练数据见表 2-10(第 27~37 段)。

  4. 出处:「2.6 算法6:朴素贝叶斯」第 88 段(text/11-ch02-06-2-6-6.txt:88,搜「BoW(Bag of Words,词袋)」)与第 90 段(text/11-ch02-06-2-6-6.txt:90,搜「忽略名词在文本中的顺序」);分词假定已完成的说明在第 130 段(搜「需要进行分词处理」)。

  5. 出处:「2.6 算法6:朴素贝叶斯」第 111 段(text/11-ch02-06-2-6-6.txt:111,搜「值设为 1,否则设为 0」);验证数据向量在第 143 段。

  6. 出处:「2.6 算法6:朴素贝叶斯」第 148 段(text/11-ch02-06-2-6-6.txt:148,搜「以下两种概率」)与第 149~150 段(搜「每个标签出现的概率」「每个单词出现的条件概率」)。

  7. 出处:「2.6 算法6:朴素贝叶斯」第 49 段(text/11-ch02-06-2-6-6.txt:49,搜「概率是 3/6 = 50%」)与第 52 段(搜「率都是固定的」)。

  8. 出处:「2.6 算法6:朴素贝叶斯」第 177 段(text/11-ch02-06-2-6-6.txt:177,搜「两个概率的乘积」)。

  9. 出处:「2.6 算法6:朴素贝叶斯」第 215 段(text/11-ch02-06-2-6-6.txt:215,搜「MultinomialNB」)与第 238 段(text/11-ch02-06-2-6-6.txt:238,搜「说明这次的判断是正确」)。 2 3

  10. 出处:「2.6 算法6:朴素贝叶斯」第 173 段(text/11-ch02-06-2-6-6.txt:173,搜「叫作平滑」)与第 175 段(text/11-ch02-06-2-6-6.txt:175,搜「真有可能出现」)。 2

  11. 出处:「2.6 算法6:朴素贝叶斯」第 206 段(text/11-ch02-06-2-6-6.txt:206,搜「没有考虑单词的顺序和组合」)与第 207 段(text/11-ch02-06-2-6-6.txt:207,搜「每个单词都是独立的」)。 2 3

  12. 出处:「2.6 算法6:朴素贝叶斯」第 243 段(text/11-ch02-06-2-6-6.txt:243,搜「降水概率那种预测值是」)与第 248 段(text/11-ch02-06-2-6-6.txt:248,搜「用作概率」)。 2

  13. 出处:「2.6 算法6:朴素贝叶斯」第 252 段(text/11-ch02-06-2-6-6.txt:252,搜「踢了球」)与第 255 段(text/11-ch02-06-2-6-6.txt:255,搜「考虑使用其他模型」)。

  14. 出处:「2.6 算法6:朴素贝叶斯」第 72 段(text/11-ch02-06-2-6-6.txt:72,搜「2/3 ≈ 67%」)。