跳转至

14.5   朴素贝叶斯

小率要把活动留言分成“咨询报名”“投诉”“闲聊”。有些留言很短:“还可以报名吗?”“教室太远了”“有没有摄影活动”。数据不多,但关键词很明显。

均哥说,这种场景可以先试 朴素贝叶斯(Naive Bayes):它用贝叶斯公式把关键词证据合在一起,快速估计每个类别的可能性。

图 14.5.0 在活动咨询台用线索卡片分类留言

为什么叫“朴素”?听起来有点不太厉害。
朴素是因为它假设特征条件独立。这个假设很强,但在文本小数据里常常很好用。

14.5.1   贝叶斯公式从证据更新类别

对一个类别 \(c\) 和一条留言 \(\mathbf{x}\),贝叶斯公式写成:

\[ P(c\mid \mathbf{x})=\frac{P(\mathbf{x}\mid c)P(c)}{P(\mathbf{x})} \]

分类时,分母 \(P(\mathbf{x})\) 对所有类别相同,所以比较:

\[ \hat c=\arg\max_c P(\mathbf{x}\mid c)P(c) \]

\(P(c)\) 是先验概率,表示每类留言原本出现的比例;\(P(\mathbf{x}\mid c)\) 是似然,表示在某个类别下看到这些词的可能性。


14.5.2   朴素假设把联合概率拆开

如果留言有很多词,直接估计 \(P(\mathbf{x}\mid c)\) 很难。朴素贝叶斯假设:在给定类别后,各个特征条件独立。

于是:

\[ P(\mathbf{x}\mid c)=\prod_{j=1}^{p}P(x_j\mid c) \]

这个假设在真实文本里并不严格成立,比如“摄影”和“展览”常常一起出现。但它让模型非常快,也不容易在小数据里过拟合。

朴素贝叶斯的优势

参数少、训练快、对高维稀疏文本友好。即使概率估计不够准,分类排序仍可能很好。


14.5.3   平滑避免零概率

如果训练集中“摄影”从未出现在“投诉”类别里,那么 \(P(\text{摄影}\mid \text{投诉})=0\),整条留言的概率会被乘成 0。常用 拉普拉斯平滑(Laplace Smoothing)

\[ P(w\mid c)=\frac{\text{count}(w,c)+\alpha}{\sum_{w'}\text{count}(w',c)+\alpha V} \]

\(V\) 是词表大小,\(\alpha\) 控制平滑强度。默认 \(\alpha=1\) 常作为起点。

平滑像是说:没见过不代表绝不可能。
对。它给每个词留一点最低可能性。

14.5.4   用 Python 做文本分类

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import make_pipeline

texts = [
    "还可以 报名 摄影 活动 吗",
    "篮球 活动 怎么 报名",
    "教室 太远 体验 不好",
    "排队 太久 投诉",
    "今晚 有 音乐 活动 吗",
    "老师 讲解 很 清楚",
]
labels = ["咨询", "咨询", "投诉", "投诉", "咨询", "闲聊"]

model = make_pipeline(CountVectorizer(), MultinomialNB(alpha=1.0))
model.fit(texts, labels)

print(model.predict(["摄影 展览 还能 报名 吗"]))

概率不一定校准

朴素贝叶斯输出的概率常常不够校准,尤其特征相关性很强时。它很适合做快速分类基线,但重要决策前要检查校准和错误代价。

小率的笔记本

朴素贝叶斯用贝叶斯公式合并证据,用条件独立假设降低估计难度。它在文本分类、小数据、高维稀疏特征中很快很稳,但概率解释要谨慎。