机器学习之朴素贝叶斯算法

一、朴素贝叶斯算法简介

1. 概述

贝叶斯算法其实不是一个单一的算法,而是一类基于贝叶斯定理 的统计方法。朴素贝叶斯(Naive Bayes) 是贝叶斯算法家族中最常用、最经典的一个具体模型。它是一种有监督学习算法,是一种利用概率值进行分类的预测模型。

核心思想:贝叶斯算法的核心思想是通过已知的证据(先验概率),预测某个假设为真的概率(后验概率)。而朴素贝叶斯在贝叶斯的基础上增加了一个"朴素"的假设------所有特征之间相互独立

2. 贝叶斯定理

贝叶斯定理是概率论中的一个基本定理,它描述了如何根据新的证据更新一个假设的概率。简单说,就是告诉你:当观察到某个现象后,原来对某件事情的信念应该改变多少。

  • 公式:
    P(A∣B)=P(B∣A)⋅P(A)P(B)P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)}P(A∣B)=P(B)P(B∣A)⋅P(A)

公式说明:

  • P(A∣B)P(A|B)P(A∣B):后验概率。在事件B发生的条件下,事件A发生的概率。
  • P(B∣A)P(B|A)P(B∣A):条件概率。在事件A发生的条件下,事件B发生的概率。
  • P(A)P(A)P(A):先验概率。在观察到任何证据前,事件A发生的概率。
  • P(B)P(B)P(B):边缘概率。事件B发生的总概率(通常作为归一化常数,在分类比较时可忽略)。

举例

我们以"判断一封包含'恭喜你中奖了'的邮件是否为垃圾邮件"为例,完整演示贝叶斯定理的计算流程:

  1. 计算先验概率(Prior Probability)

    从历史数据中统计,100封邮件里有30封是垃圾邮件,因此:

    • 垃圾邮件的先验概率:P(垃圾)=0.3P(\text{垃圾}) = 0.3P(垃圾)=0.3
    • 正常邮件的先验概率:P(正常)=1−P(垃圾)=0.7P(\text{正常}) = 1 - P(\text{垃圾}) = 0.7P(正常)=1−P(垃圾)=0.7
  2. 计算似然概率(Likelihood)

    统计不同类别邮件中出现关键词"恭喜"的概率:

    • 垃圾邮件中出现"恭喜"的概率:P(恭喜∣垃圾)=0.4P(\text{恭喜}|\text{垃圾}) = 0.4P(恭喜∣垃圾)=0.4
    • 正常邮件中出现"恭喜"的概率:P(恭喜∣正常)=0.1P(\text{恭喜}|\text{正常}) = 0.1P(恭喜∣正常)=0.1
  3. 计算全概率(Total Probability)

    根据全概率公式,计算所有邮件中出现"恭喜"一词的总概率:

    P(恭喜)=P(恭喜∣垃圾)P(垃圾)+P(恭喜∣正常)P(正常)=0.4×0.3+0.1×0.7=0.12+0.07=0.19 \begin{align*} P(\text{恭喜}) &= P(\text{恭喜}|\text{垃圾})P(\text{垃圾}) + P(\text{恭喜}|\text{正常})P(\text{正常}) \\ &= 0.4 \times 0.3 + 0.1 \times 0.7 \\ &= 0.12 + 0.07 \\ &= 0.19 \end{align*} P(恭喜)=P(恭喜∣垃圾)P(垃圾)+P(恭喜∣正常)P(正常)=0.4×0.3+0.1×0.7=0.12+0.07=0.19

  4. 计算后验概率(Posterior Probability)

    使用贝叶斯定理,计算"邮件中出现'恭喜'时,它是垃圾邮件的概率":

    P(垃圾∣恭喜)=P(恭喜∣垃圾)⋅P(垃圾)P(恭喜)=0.4×0.30.19≈0.6316 \begin{align*} P(\text{垃圾}|\text{恭喜}) &= \frac{P(\text{恭喜}|\text{垃圾}) \cdot P(\text{垃圾})}{P(\text{恭喜})} \\ &= \frac{0.4 \times 0.3}{0.19} \\ &\approx 0.6316 \end{align*} P(垃圾∣恭喜)=P(恭喜)P(恭喜∣垃圾)⋅P(垃圾)=0.190.4×0.3≈0.6316

  5. 最终决策

    计算结果表示:当邮件中出现"恭喜"一词时,它是垃圾邮件的概率约为 63.16% ,大于正常邮件的后验概率(P(正常∣恭喜)≈36.84%P(\text{正常}|\text{恭喜}) \approx 36.84\%P(正常∣恭喜)≈36.84%),因此模型判定这封邮件为垃圾邮件。

3. 拉普拉斯平滑系数

拉普拉斯平滑(Laplace Smoothing),也叫加一平滑 ,是朴素贝叶斯算法中为了解决 零概率问题 而引入的一种技术。拉普拉斯平滑通过给每个特征的计数加上一个小的伪计数来避免这种零概率。

  • 公式:
    P(F1∣C)=Ni+αN+αmP(F_1|C) = \frac{N_i + \alpha}{N + \alpha m}P(F1∣C)=N+αmNi+α

公式说明:

α 是拉普拉斯平滑系数,一般指定为 1

Ni 是 F1 中符合条件 C 的样本数量

N 是在条件 C 下所有样本的总数

m 表示所有独立样本的总数

4. 构建流程

  • 数据准备与预处理:数据清洗、分词、统计词频(转为向量化特征数据)。
  • 模型训练:计算概率(先验概率、条件概率、边缘概率),训练和保存模型。
  • 模型预测:计算后验概率,选择概率最高的作为预测结果。
  • 评估调优 :通过准确率、精确率、F1值对模型进行评估,使用交叉验证选择最优的平滑系数α\alphaα,通过特征选择提高模型泛化能力。

二、常见的算法模型

  • 高斯朴素贝叶斯:适用于特征为连续值,且服从正态分布的数据。
  • 多项式朴素贝叶斯:适用于特征为离散值,如文本的词频计数。
  • 伯努利朴素贝叶斯:适用于特征为二元值(0/1),如判断某个词是否出现。

三、优缺点

  • 优点
    • 简单高效:原理简单,易于理解和实现,训练和预测速度极快。
    • 适合高维数据:特别适用于文本分类这种特征维度(词汇量)非常高的场景。
    • 对小规模数据表现好:即使训练数据量不大,也能取得不错的效果。
    • 多分类友好:天然支持多类别分类。
    • 对缺失数据不敏感:对噪声数据有一定的容忍度。
  • 缺点
    • 强独立性假设:现实中数据特征往往存在关联,这个假设过于理想化。
    • 零概率问题 :对于未见过的特征值,会出现零概率问题(可通过拉普拉斯平滑修正)。
    • 先验概率影响大:如果先验概率设置不准确(即训练集类别分布与真实分布偏差大),会影响预测结果。

四、应用场景及案例演示

1. 应用场景

  • 垃圾邮件过滤:判断邮件是正常邮件还是垃圾邮件。
  • 情感分析:判断评论、推文的情感倾向(正面/负面)。
  • 新闻/文档自动分类:将文章归类到政治、体育、科技等板块。

2. 案例演示

python 复制代码
"""
案例:
    演示通过 朴素贝叶斯算法 实现 商品评论情感分析, 即: 好评, 差评...

朴素贝叶斯介绍:
    概述:
        贝叶斯: 仅仅依靠概率就可以进行分类的一种机器学习算法.
        朴素: 不考虑特征之间的关联性, 即: 特征间都是相互独立的.
            原始: P(AB) = P(A) * P(B|A) = P(B) * P(A|B)
            加入朴素后: P(AB) = P(A) * P(B)
"""

# 导包
import numpy as np  # 数学计算包
import pandas as pd  # 数据处理包
import jieba  # 分词包
from sklearn.feature_extraction.text import CountVectorizer  # 词频统计包, 把评论内容转成词频矩阵
from sklearn.metrics import accuracy_score
from sklearn.naive_bayes import MultinomialNB  # 朴素贝叶斯对象

# 1. 读取文件, 获取到原始数据.
df = pd.read_csv('data/书籍评价.csv', encoding='gbk')

# 2. 数据预处理
# 2.1 添加labels列, 充当: 标签列表, 好评 -> 1, 差评 -> 0
df['labels'] = np.where(df['评价'] == '好评', 1, 0)
# df.info()
# print(df.head())

# 2.2 抽取labels列, 作为标签
y = df['labels']

# 2.3 演示jieba切词
# print(jieba.lcut('我是中国少先队队员'))

# 2.4 对用户的评论信息, 做切词
comment_list = [','.join(jieba.lcut(line)) for line in df['内容']]
# print(comment_list)

# 2.5 加载停用词列表, 即: 里面记录的词, 不要参与模型训练, 预测, 要删除的词, 例如: 的, 啊, 哈, 从, 都...
with open('data/stopwords.txt', encoding='utf-8') as f:
    # 2.5.1 一次性读取所有行
    stopwords_list = f.readlines()
    # 2.5.2 删除最后的\n
    stopwords_list = [line.strip() for line in stopwords_list]
    # 2.5.3 对停用词进行去重
    stopwords_list = list(set(stopwords_list))
    # print(stopwords_list)

# 2.6 创建向量化对象, 从评论切词列表(comment_list)中删除停用词, 并统计词频(单词矩阵)
transfer = CountVectorizer(stop_words=stopwords_list)  # 参数: 停用词列表
# 2.7 统计词频矩阵, 先训练, 后转换, 再转数组
transfer.fit(comment_list)
# x的格式: [[第1条评论的切词分布, 有就是1, 没有就是0], [第2条评论的切词分布, 有就是1, 没有就是0]...]
x = transfer.transform(comment_list).toarray()
print(x)
# 2.8 看一下我们13条评论, 切词, 且删除停用词后, 剩下多少词
print(transfer.get_feature_names_out())
# 2.9 因为就13条数据, 我们把前10条当训练集, 后3条当测试集
x_train = x[:10]
y_train = y[:10]
x_test = x[10:]
y_test = y[10:]
# 3. 特征工程, 此处略

# 4. 模型训练
estimator = MultinomialNB()
estimator.fit(x_train, y_train)

# 5 模型预测
y_pred = estimator.predict(x_test)
print(f'模型的预测结果为: {y_pred}')

# 6. 模型评估
print(f'模型的准确率为: {accuracy_score(y_test, y_pred)}')
相关推荐
weixin_BYSJ19871 小时前
springboot旅游管理系统04470(附源码+开发文档+部署教程)
java·spring boot·python·算法·django·flask·旅游
MobotStone1 小时前
AI正在改变的,不是岗位,而是整个企业的运营模式
人工智能
8Qi81 小时前
LeetCode 209. 长度最小的子数组(Minimum Size Subarray Sum)
java·算法·leetcode·双指针·滑动窗口
Nile1 小时前
解密Palantir系列一:3. Palantir 是谁
大数据·人工智能·ai
m0_380167141 小时前
加密市场数据的未来:实时化、多交易所与 AI-ready
人工智能·区块链
云天AI实战派1 小时前
AI 智能体总是跑偏怎么办?ChatGPT/API/Agent 故障排查指南与全流程修复手册
大数据·人工智能·chatgpt·agent
星浩AI1 小时前
(六)模型微调效果测试:基于 BERT 的中文评价情感分析[附源码]
人工智能·机器学习·llm
smile-yan1 小时前
大厂故事之百度(3/4)AI商业化迷航——从技术强到落地难
人工智能·百度
vensli1 小时前
消息跨端架构演进:基于 C++ 的多端一致性研发框架实践
java·人工智能·软件工程·安卓