朴素贝叶斯把分类问题写成概率比较:看到这些特征后,哪一个类别更可能?它通过条件独立假设简化计算,因此训练成本较低,适合作为文本分类基线。特征在现实中并不需要真的互不相关;关键是这种近似会怎样影响分类结果和概率可信度。
原理:贝叶斯定理 + 一个天真的假设
分类问题写成概率:已知特征 ,求最可能的类别:
困难在 ——特征有几千维时,这个联合分布没法估。朴素贝叶斯的”天真”假设:特征之间条件独立(给定类别,各特征互不影响)。于是联合概率拆成逐个特征的乘积:
每个 只要在训练集上数数就能估出来。假设显然是假的(“免费”和”发票”在垃圾邮件里明明相关),但实践反复证明:假设错误不妨碍分类效果好——因为分类只要求正确类别的概率最大,不要求概率值本身精确。
实战:垃圾邮件过滤 20 行代码
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline
# 多项分布变体:处理词频计数,文本分类的标准选择
pipe = Pipeline([
("vec", CountVectorizer(ngram_range=(1, 2), min_df=3)),
("nb", MultinomialNB(alpha=1.0)), # alpha 是平滑参数
])
pipe.fit(train_texts, train_labels)
print(pipe.score(test_texts, test_labels))
# 看看模型认为哪些词最"垃圾"
import numpy as np
vec, nb = pipe["vec"], pipe["nb"]
words = np.array(vec.get_feature_names_out())
spam_log = nb.feature_log_prob_[1] - nb.feature_log_prob_[0]
print(words[np.argsort(spam_log)[-10:]]) # 最指向垃圾邮件的词
alpha 是拉普拉斯平滑:训练集里没出现过的词,计数为 0 会导致整个乘积变 0(一个词没见过,邮件就被判死刑)。平滑给所有计数加一个底数,没见过不等于不可能。alpha 通常 0.1-1.0,是重要的调参点。
三种变体:按特征形态选
| 变体 | 特征假设 | 适用 |
|---|---|---|
| MultinomialNB | 词频计数(多项分布) | 文本分类首选 |
| BernoulliNB | 词出现/不出现(0/1) | 短文本、特征本身是二值的 |
| GaussianNB | 连续特征服从正态分布 | 数值特征、快速基线 |
文本场景记住:词频用多项版,词袋布尔值用伯努利版。把词频喂给伯努利版(它会把所有非零都当 1)是常见错误,会丢掉词频信息。
它的真实定位:快基线 + 可解释
朴素贝叶斯的优势清单:训练毫秒级(一遍数数)、小数据表现好(参数少不怕过拟合)、天然输出概率、特征对类别的贡献直接可查(feature_log_prob_ 差值就是证据权重)。它至今是任何文本分类任务的第一基线——领域分类的逻辑回归基线之前,先用它十分钟立个下限。
短板也明确:特征独立假设让它无法理解词之间的组合(“不 推荐”和”推荐”在它眼里差不多,ngram 特征能部分缓解);概率输出虽然快但校准不准(排序可用,当精确概率用要校准)。
踩坑排查
| 症状 | 原因 | 处理 |
|---|---|---|
| 预测全是某一类 | 先验悬殊没处理 | class_prior 调整;评估看宏 F1 |
| 遇到新词就崩 | 没设平滑 | alpha > 0(默认 1.0 即可) |
| 用错变体效果差 | 词频喂了伯努利 | 文本词频用 MultinomialNB |
| 概率值极端(0.99/0.01) | NB 概率本性 | 排序可用;要准概率做校准 |
| 长文档效果差 | 词频随长度膨胀 | 归一化或换 TF-IDF + 线性模型 |
练习
- 在 20newsgroups 子集上对比三种变体的分数,解释差异来源。
- 扫 alpha ∈ {0.01, 0.1, 1, 10},观察对验证分的影响并解释平滑的作用。
- 提取最指向各类别的 Top 10 词,人工检查可解释性。
- 对比朴素贝叶斯与逻辑回归在小样本(500 条)和大样本(5 万条)下的表现。
面试常问
Q:朴素贝叶斯为什么”朴素”? 假设特征条件独立。现实中几乎从不成立,但分类只比较各类别后验的相对大小,独立性假设的误差在所有类别上同向存在,排序常常仍然正确——这是它”假设错但效果好”的原因。
Q:拉普拉斯平滑解决什么? 训练集中未出现的特征-类别组合概率为 0,乘法链中一个 0 就判死刑。平滑给计数加底数 α,未见事件获得小而非零的概率。
Q:朴素贝叶斯和逻辑回归的关系? 都是线性分类器(NB 的对数几率是特征的线性函数),但训练目标不同:NB 是生成式(学 P(x|y) 和 P(y)),逻辑回归是判别式(直接学 P(y|x))。数据少时生成式的 NB 常有优势,数据多时判别式上限更高(Ng & Jordan 的经典结论)。
Q:为什么 NB 适合小数据? 参数少(每类每特征一个计数),估计方差小,不易过拟合;复杂模型在小数据上估不准参数。这是”简单模型的偏差换方差”的典型案例。
💬 评论
这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。