朴素贝叶斯入门到精通:从理论公式到手写数字识别实战
贝叶斯定理解决了 “由果推因” 的问题,但如果数据有多个特征(比如邮件包含多个单词),计算 “多特征的联合似然” 会非常复杂。这就是 “朴素” 的核心含义 —— 虽然这个假设在现实中不一定完全成立(比如文本中 “机器学习” 和 “人工智能” 可能相关),但它能让模型变得简单、高效,且在很多场景下效果很好。这是我们熟悉的概率计算 —— 已知 “原因”(球的比例),求 “结果”(摸出某颜色球的概率),
一、从贝叶斯定理说起:解决 “逆向概率” 问题
要理解朴素贝叶斯,首先得搞懂它的 “基石”——贝叶斯定理。而理解贝叶斯定理的关键,是区分 “正向概率” 和 “逆向概率”。
1.1 正向概率 vs 逆向概率:生活中的直观例子
先看两个简单的问题,帮你快速分清这两个概念:
-
正向概率:已知袋子里有 6 个白球、4 个黑球,伸手摸一个,摸出黑球的概率是多少?
这是我们熟悉的概率计算 —— 已知 “原因”(球的比例),求 “结果”(摸出某颜色球的概率),公式很直接:黑球概率 = 黑球数量 / 总球数 = 4/(6+4) = 40%。 -
逆向概率:闭着眼睛摸出 1 个黑球,现在要推测袋子里黑白球的比例可能是多少?
这就反过来了 —— 已知 “结果”(摸出黑球),求 “原因”(球的比例)。这种 “由果推因” 的问题,正是贝叶斯定理要解决的核心。
二、朴素贝叶斯:为什么 “朴素”?
贝叶斯定理解决了 “由果推因” 的问题,但如果数据有多个特征(比如邮件包含多个单词),计算 “多特征的联合似然” 会非常复杂。比如垃圾邮件分类中,若邮件有 10 个单词,似然 P (D|h) 需要计算 “10 个单词同时出现” 的概率,这会涉及大量参数,几乎无法实现。
这时,朴素贝叶斯的 “朴素(Naive)” 假设就派上用场了 ——假设所有特征之间相互独立,互不影响。
也就是说,每个特征的似然可以单独计算,再相乘即可。这就是 “朴素” 的核心含义 —— 虽然这个假设在现实中不一定完全成立(比如文本中 “机器学习” 和 “人工智能” 可能相关),但它能让模型变得简单、高效,且在很多场景下效果很好。
三、经典实例:朴素贝叶斯如何解决实际问题?
理论讲完,我们用两个经典实例,看看朴素贝叶斯在实际中是如何工作的。
实例 1:拼写纠正 —— 猜用户想输什么词
当用户输入一个不在字典里的词(比如 “tlp”),我们需要推测他真正想输的词(是 “top” 还是 “tip”?)。
核心逻辑:比较不同假设的后验概率
- 观测数据 D:用户输入的 “tlp”
- 假设 h1:想输 “top”;假设 h2:想输 “tip”
- 后验概率 P (h|D) ∝ P (h) × P (D|h)(因 P (D) 是常数,可忽略)
两步计算:
- 先验概率 P (h):某个词在日常使用中出现的频率。比如 “top” 出现的频率远高于 “tip”,所以 P (top) > P (tip)。
- 似然 P (D|h):“想输 h,却错输成 D” 的概率。比如 “top” 错输成 “tlp”(只错 1 个字母)的概率,比 “tip” 错输成 “tlp”(错 2 个字母)的概率高,所以 P (tlp|top) > P (tlp|tip)。
结论:
P (top)×P (tlp|top) > P (tip)×P (tlp|tip),因此推测用户想输 “top”。
实例 2:垃圾邮件分类 —— 判断邮件是否为垃圾
给定一封邮件(含多个单词),判断它是垃圾邮件(h+)还是正常邮件(h-)。
核心逻辑:计算两类邮件的后验概率
- 观测数据 D:邮件中的单词集合 {d1, d2, ..., dn}(比如 “中奖”“转账”“领取”)
- 后验概率:
P(h+∣D)=P(D)P(h+)×P(d1∣h+)×P(d2∣h+)×...×P(dn∣h+)
P(h−∣D)=P(D)P(h−)×P(d1∣h−)×P(d2∣h−)×...×P(dn∣h−) - 比较 P (h+|D) 和 P (h-|D),哪个大就归为哪类。
关键参数计算:
- 先验概率 P (h+) 和 P (h-):统计邮件库中垃圾邮件和正常邮件的比例。比如 1000 封邮件中有 300 封垃圾邮件,则 P (h+) = 30%,P (h-) = 70%。
- 似然 P (di|h+):单词 di 在垃圾邮件中出现的频率。比如 “中奖” 在 300 封垃圾邮件中出现 150 次,则 P (中奖 | h+) = 150/300 = 50%。
- 注意:若某个单词在垃圾邮件中没出现(概率为 0),会导致整个乘积为 0,此时需要用拉普拉斯平滑(给分子分母加一个小常数,比如 alpha=1),避免概率为 0。
四、三种常用朴素贝叶斯变体:该选哪一个?
根据特征的数据类型不同,朴素贝叶斯衍生出了三种常用变体。在 Sklearn 中,我们可以直接调用对应的 API,关键是选对适合自己数据的模型。
1. 多项式朴素贝叶斯(MultinomialNB)
适用场景:离散型特征(如文本分类中的 “单词出现次数”)
核心思想:假设特征服从 “多项式分布”(统计每个特征的出现次数)
Sklearn 参数解析:
参数 | 含义 |
---|---|
alpha | 拉普拉斯平滑系数,默认 1.0(alpha=0 表示不平滑,避免概率为 0) |
fit_prior | 是否考虑先验概率,默认 True(False 则假设所有类别的先验概率相等) |
class_prior | 自定义类别的先验概率,默认 None(若为 None 则从数据中统计) |
代码示例(文本分类):
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
# 1. 准备数据(简单文本示例)
texts = ["你好 今天天气不错", "中奖 请转账 领取奖金", "工作汇报 明天提交", "免费 领取 奖品 点击链接"]
labels = [0, 1, 0, 1] # 0=正常,1=垃圾
# 2. 文本转离散特征(统计单词出现次数)
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(texts) # 特征矩阵:每行是一个文本的词频
# 3. 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25)
# 4. 训练模型
model = MultinomialNB(alpha=1.0)
model.fit(X_train, y_train)
# 5. 预测与评估
score = model.score(X_test, y_test)
print(f"模型准确率:{score}")
2. 高斯朴素贝叶斯(GaussianNB)
适用场景:连续型特征(如身高、体重、温度等)
核心思想:假设特征服从 “高斯分布(正态分布)”,通过计算均值和方差来估计似然
Sklearn 参数解析:
参数 | 含义 |
---|---|
priors | 自定义类别的先验概率,默认 None(若为 None 则从数据中用极大似然法计算) |
代码示例(基于 Iris 数据集):
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 1. 加载数据(Iris特征是连续型:花瓣长度、宽度等)
iris = load_iris()
X = iris.data # 连续特征
y = iris.target # 类别标签
# 2. 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 3. 训练模型
model = GaussianNB()
model.fit(X_train, y_train)
# 4. 预测与评估
score = model.score(X_test, y_test)
print(f"模型准确率:{score}")
3. 伯努利朴素贝叶斯(BernoulliNB)
适用场景:二值型特征(特征值只有 0 或 1,如 “单词是否出现”“是否点击链接”)
核心思想:假设特征服从 “伯努利分布”(只关注特征 “是否存在”,不关注出现次数)
Sklearn 参数解析:
参数 | 含义 |
---|---|
alpha | 拉普拉斯平滑系数,默认 1.0 |
binarize | 特征二值化阈值,默认 0(若特征未二值化,可设此值将连续特征转为 0/1) |
fit_prior | 是否考虑先验概率,默认 True |
class_prior | 自定义类别的先验概率,默认 None |
代码示例(二值化文本分类):
from sklearn.naive_bayes import BernoulliNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
# 1. 准备数据
texts = ["你好 今天天气不错", "中奖 请转账 领取奖金", "工作汇报 明天提交", "免费 领取 奖品 点击链接"]
labels = [0, 1, 0, 1]
# 2. 文本转二值特征(单词是否出现:1=出现,0=不出现)
vectorizer = CountVectorizer(binary=True) # binary=True表示二值化
X = vectorizer.fit_transform(texts)
# 3. 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25)
# 4. 训练模型
model = BernoulliNB(alpha=1.0)
model.fit(X_train, y_train)
# 5. 预测与评估
score = model.score(X_test, y_test)
print(f"模型准确率:{score}")
更多推荐
所有评论(0)