一、从贝叶斯定理说起:解决 “逆向概率” 问题

要理解朴素贝叶斯,首先得搞懂它的 “基石”——贝叶斯定理。而理解贝叶斯定理的关键,是区分 “正向概率” 和 “逆向概率”。

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) 是常数,可忽略)
两步计算:
  1. 先验概率 P (h):某个词在日常使用中出现的频率。比如 “top” 出现的频率远高于 “tip”,所以 P (top) > P (tip)。
  2. 似然 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),哪个大就归为哪类。
关键参数计算:
  1. 先验概率 P (h+) 和 P (h-):统计邮件库中垃圾邮件和正常邮件的比例。比如 1000 封邮件中有 300 封垃圾邮件,则 P (h+) = 30%,P (h-) = 70%。
  2. 似然 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}")
Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐