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

2023-11-18

1.引言

贝叶斯方法是一个历史悠久,有着坚实的理论基础的方法,同时处理很多问题时直接而又高效,很多高级自然语言处理模型也可以从它演化而来。因此,学习贝叶斯方法,是研究自然语言处理问题的一个非常好的切入口。

2.朴素贝叶斯分类方法

前面学的knn算法,是看结果划分到哪个类。而朴素贝叶斯的结果是分完以后讲样本归类到后验概率最大的那个类。本节典型的例子是垃圾短信,邮箱的分类。
在这里插入图片描述
流程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.概率基础

在这里插入图片描述

问题1:垃圾短信的概率?
问题2:信息含字母A(内容为AAA)且含字母B(内容为AAB)的概率?
问题3:在是垃圾短息的情况下,含字母A内容为AAA的概率?
问题4:在不是垃圾短息的情况下,含字母A内容为AAA的,且含字母B(内容为AAB)概率?

答案1: P(垃圾短信): 3/9 ==1/3
答案2:在这里插入图片描述
P(AAA,AAB) = 2/9

答案3: P(AAA|垃圾短息)= 0/3 = 0
在这里插入图片描述

答案4:P(AAA,AAB|不是垃圾短信)= 2/(9-3) = 1/3

贝叶斯公式:
在这里插入图片描述

注意:我们计算出某个概率为0,合适吗?
问题3求出的答案是0,得到0的结果是由于样例较少,这里引入一个处理方法:拉普拉斯平滑系数(目的:防止计算出的分类概率为0)
在这里插入图片描述
解决问题3: P(AAA|垃圾短信)= 分子:0+1 分母:特征词出现的个数:5个特
征词有AAA,AAB,AAC,ABC,FDSAEB
最终答案:P(AAA|垃圾短信)= 0+1/3+5 = 1/8

4.朴素贝叶斯特征提取

# 导入TfidfVectorizer
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer


# 输入训练集矩阵,每行表示一个文本
train = ["生活是一种律动,须有光有影,有左有右,有晴有雨,趣味就在这变而不猛的曲折里,微微暗些,再明起来,则暗得有趣,而明乃更明",
         "照片这种东西不过是生命的碎壳,纷纷的岁月已过去,瓜子仁一粒粒咽了下去,滋味各人知道,留给大家看的唯有那狼藉的黑白的瓜子壳",
         "有才而性缓定属大才,有智而气和斯为大智,人褊急我受之以宽容,人险仄我持之以坦荡。缓事宜急干,敏则有功;急事宜缓办,忙则多错",
         "才不足则多谋,识不足则多虑,威不足则多怒,信不足则多言,勇不足则多劳,明不足则多察,理不足则多辩,情不足则多仪"]

# 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
def cut_test(train):
    te = ' '.join(list(jieba.cut(train)))
    return te
def tf():
    train_new = []
    for i in train:
        train_new.append(cut_test(i))
    # 实例化tf实例
    tv = TfidfVectorizer(use_idf=True, smooth_idf=True, norm=None)
    tv_fit = tv.fit_transform(train_new)
    # 查看一下构建的词汇表
    print(tv.get_feature_names_out())
    # 查看输入文本列表的VSM矩阵
    print(tv_fit.toarray())

if __name__ == '__main__':
    tf()

5.朴素贝叶斯分类的sklearn实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.垃圾短息分类

#!/usr/bin/env python
# encoding: utf-8
"""
思路:
1、数据集读取,数据处理及训练集和测试集划分
2、选取不同分布的朴素贝叶斯模型进行分类模型训练与测试、评价
"""
import pandas as pd
import warnings

from sklearn.feature_extraction.text import TfidfVectorizer  # 文本型数据处理
from sklearn.preprocessing import LabelEncoder  # 字符串型数据编码
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB, BernoulliNB, MultinomialNB
from sklearn.metrics import roc_curve, auc
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

from matplotlib import rcParams
import matplotlib
# matplotlib.use("Agg")  # 输出时不显示绘图
import matplotlib.pyplot as plt  # matplotlib.use('agg')必须在本句执行前运行

rcParams['font.family'] = 'simhei'  # 可以让图像中显示中文(黑体),无需引用
rcParams['axes.unicode_minus'] = False  # 解决负数坐标显示问题
warnings.filterwarnings('ignore')

# #############################################################################################
# 公共部分:分类模型评价体系evaluation
# todo: 构建分类模型的评价体系并存储在evaluation中,方便对比查看,全局变量
evaluation = pd.DataFrame({'Model': [],
                           '准确率': [],
                           '精确率': [],
                           '召回率': [],
                           'F1 值': [],
                           'AUC值': [],
                           '5折交叉验证的score': []})


# #############################################################################################
# 步骤1 todo: 数据读取、单词文本处理及标签数值化处理、数据集划分
def data_preprocess(train_size):
    # 步骤1.1 todo: 读取数据并统计数据类别信息
    df = pd.read_csv('./data/SMSSpamCollection', delimiter='\t', header=None)  # 利用pandas直接读取已有数据,数据以tab分割
    print(df.describe())  # 了解数据的基本信息
    print('为spam短信数量:', df[df[0] == 'spam'][0].count())
    print('为ham短信数量:', df[df[0] == 'ham'][0].count())

    # 步骤1.2 todo: 对数据集中单词文本进行处理
    # 由于数据集为单词文本数据,构建TfidfVectorizer来计算每个单词的TF-IDF权重
    tfidf_vectorizer = TfidfVectorizer()
    X = tfidf_vectorizer.fit_transform(df[1])
    X = X.toarray()  # 将数据矩阵转化为数组
    voc = tfidf_vectorizer.get_feature_names_out()  # 构建的词汇表
    print(len(voc))

    # 步骤1.3 todo: 目标变量中为字符串型数据,使用labelEncoder处理(spam-1,ham-0)
    le = LabelEncoder()  # 对定型特征多值化
    y = le.fit_transform(df[0])

    # 步骤1.4 todo: 对整体数据按照train_size进行划分,得到训练集和测试集, random_state确保结果的一致性
    X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=train_size, random_state=0)

    return X_train, y_train, X_test, y_test, df


# #############################################################################################
# 步骤2 todo: 进行朴素贝叶斯分类模型训练与测试、评价
# 由于选取的不同分布的朴素贝叶斯分类器,写成函数形式,便于引用
def naive_bayes_with_diff_distribution(model, model_name, X_train, y_train, X_test, y_test):
    # 步骤2.1 todo: 调用不同分布的朴素贝叶斯分类实例,进行训练测试
    NB_model = model
    NB_model.fit(X_train, y_train)
    y_test_predict = NB_model.predict(X_test)

    # 步骤2.2 todo: 计算分类评价指标:测试集的准确率accuracy、精确率precision、召回率recall和综合评价指标 F1 值
    # 精确率是指分类器预测出的垃圾短信中真的是垃圾短信的比例
    # 召回率是所有真的垃圾短信被分类器正确找出来的比例
    # F1 值是精确率和召回率的调和均值
    acc_test = accuracy_score(y_test, y_test_predict)  # 和模型自带的score一致
    precision_test = precision_score(y_test, y_test_predict)
    recall_test = recall_score(y_test, y_test_predict)
    f1score_test = f1_score(y_test, y_test_predict)

    # 步骤2.3 todo: 绘制ROC曲线,计算auc,度量分类模型的预测能力
    # ROC曲线以召回率为纵轴,以假正例率为横轴,ROC曲线下的面积为AUC值
    y_test_predict_proba = NB_model.predict_proba(X_test)
    false_positive_rate, recall, thresholds = roc_curve(y_test, y_test_predict_proba[:, 1])
    roc_auc = auc(false_positive_rate, recall)  # 计算auc的值
    plt.figure()
    plt.title('%s 模型的 ROC-AUC 图' % model_name)
    plt.plot(false_positive_rate, recall, 'r', label='AUC = %0.3f' % roc_auc)
    plt.legend(loc='best')
    plt.plot([0, 1], [0, 1], 'k--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.0])
    plt.ylabel('真正例率(召回率)')
    plt.xlabel('假正例率')
    plt.savefig('./results/ROC_AUC_with_model_{}.png'.format(model_name))
    plt.show()

    # 步骤2.4 todo: 计算测试集的5折交叉验证的score
    cv_test = float(format(cross_val_score(NB_model, X_test, y_test, cv=5).mean(), '.3f'))

    # 步骤2.5 todo: 将朴素贝叶斯分类模型计算的相关评价信息存入evaluation中
    r = evaluation.shape[0]
    evaluation.loc[r] = ['{}分类模型'.format(model_name), acc_test,
                         precision_test, recall_test, f1score_test, roc_auc, cv_test]

    # 步骤2.6 todo: 将评价指标写入csv文件中,便于查看
    evaluation.to_csv('./results/evaluation.csv', sep=',', header=True, index=True,
                      encoding='utf_8_sig')  # encoding防止中文乱码


# #############################################################################################
# 程序入口
if __name__ == '__main__':
    # 步骤1 todo: 读取数据集,并给出训练集和测试集
    train_size = 0.67
    X_train, y_train, X_test, y_test, df = data_preprocess(train_size)

    # 步骤2 todo: 进行朴素贝叶斯分类模型训练与测试、评价
    # 'GaussianNB':Gauss朴素贝叶斯
    # 'BernoulliNB':伯努利朴素贝叶斯
    # 'MultinomialNB':多项式朴素贝叶斯
    models = [GaussianNB(), BernoulliNB(), MultinomialNB()]
    model_names = ['GaussianNB', 'BernoulliNB', 'MultinomialNB']
    for i, model in enumerate(models):
        naive_bayes_with_diff_distribution(model, model_names[i], X_train, y_train, X_test, y_test)

    print('模型测试结束!')

源码:阿里云盘地址

补充

一、先验概率:

通过经验来判断事情发生的概率 ,比如说“贝叶斯”的发病率是万分之一,就是先验概率。再比如南方的梅雨季是 6-7 月,就是通过往年的气候总结出来的经验,这个时候下雨的概率就比其他时间高出很多。

二、后验概率:

后验概率就是发生结果之后,推测原因的概率。 比如说某人查出来了患有“贝叶斯”,那么患病的原因可能是 A、B 或 C。患有“贝叶斯”是因为原因 A 的概率就是后验概率。它是属于条件概率的一种。

三、条件概率:

事件 A 在另外一个事件 B 已经发生条件下的发生概率, 表示为 P(A|B),读作“在 B 发生的条件下 A 发生的概率”。比如原因 A 的条件下,患有“贝叶斯”的概率,就是条件概率。

对于离散值的分类,对于连续值的分类
对于离散值我们直接进行概率计算,对于连续的值我们需要将其看成正态分布,然后计算均值和标准差,通过均值和标准差来求解概率。

Sklearn提供了3个朴素贝叶斯算法:
高斯朴素贝叶斯: 特征变量是连续变量,符合高斯分布,比如说人的身高,物体的长度。

多项式朴素贝叶斯: 特征变量是离散变量,符合多项分布,在文档分类中特征变量体现在一个单词出现的次数,或者是单词的 TF-IDF 值等。

伯努利朴素贝叶斯: 特征变量是布尔变量,符合 0/1 分布,在文档分类中特征是单词是否出现。

TF-IDF值:
词频 TF 计算了一个单词在文档中出现的次数,它认为一个单词的重要性和它在文档中出现的次数呈正比。

计算公式:词频 TF=单词出现的次数/该文档的总单词数
1
逆向文档频率 IDF ,是指一个单词在文档中的区分度。它认为一个单词出现在的文档数越少,就越能通过这个单词把该文档和其他文档区分开。IDF 越大就代表该单词的区分度越大。

计算公式:逆向文档频率 IDF=log(文档总数/该单词出现的文档数+1)
1
TF-IDF 实际上是词频 TF 和逆向文档频率 IDF 的乘积 。这样我们倾向于找到 TF 和 IDF 取值都高的单词作为区分,即这个单词在一个文档中出现的次数多,同时又很少出现在其他文档中。这样的单词适合用于分类。

例子
假设一个文件夹里一共有 10 篇文档,其中一篇文档有 1000 个单词,“this”这个单词出现 20 次,“bayes”出现了 5 次。“this”在所有文档中均出现过,而“bayes”只在 2 篇文档中出现过。我们来计算一下这两个词语的 TF-IDF 值。

针对“this”,计算 TF-IDF 值:

词频 TF =20/100=0.02
逆向文档频率 IDF = log(10/10+1)=-0.0414

TF-IDF=0.02*(-0.0414)=-8.28e-4。
1
2
3
4
针对“bayes”,计算 TF-IDF 值:

词频 TF =5/1000=0.005
逆向文档频率 IDF = log(10/2+1)=0.5229

TF-IDF=0.005 * 0.5229=2.61e-3。
1
2
3
4
总结:
“bayes”的 TF-IDF 值要大于“this”的 TF-IDF 值。这就说明用“bayes”这个单词做区分比单词“this”要好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习——朴素贝叶斯算法 的相关文章

随机推荐

  • 认识Java虚拟机中的类加载子系统和执行引擎

    目录 一 JVM整体架构 二 JVM类装载子系统 一 类加载过程 二 类加载器 三 类加载机制 1 全盘负责委托机制 2 双亲委派机制 Parents Delegation Model
  • XMT.com超200万被区块链终端交易

    链客 专为开发者而生 有问必答 此文章来自区块链技术社区 未经允许拒绝转载 狭义来讲 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构 并以密码学方式保证的不可篡改和不可伪造的分布式账本 当下 区块链俨然成为炙手可
  • c语言基础(一)——预处理详解

    目录 1 预处理是什么 2 预定义符号 3 define标识符 3 1 define 定义标识符 3 2 define定义宏 命名约定 3 3 宏的题目 4 和 4 1 的作用 4 2 的作用 5 带副作用的宏参数 6 宏与函数的对比 7
  • Nomad系列-Nomad网络模式

    系列文章 Nomad 系列文章 概述 Nomad 的网络和 Docker 的也有很大不同 和 K8s 的有很大不同 另外 Nomad 不同版本 Nomad 1 3 版本前后 或是否集成 Consul 及 CNI 等不同组件也会导致网络模式各
  • python中多进程(multiprocessing)

    python中多进程 multiprocessing 一 multiprocessing中使用子进程概念 from multiprocessing import Process 可以通过Process来构造一个子进程 p Process t
  • USB匹配电阻

    做过USB的人都或许有一个纠结 那就是D 和D 上到底要串多大的电阻 串在源端还是终端 我想说 网络上的说法都不完全正确 首先USB有低速 全速和高速之分 在低速和全速模式下是电压驱动的 驱动电压为3 3V 但在高速模式下是电流驱动的 驱动
  • 计算机组成原理期末复习【超实用】

    计算机组成原理 第二版 唐朔飞 编著 课本有些地方还不错 可以下载电子版看看 b站2小时讲解链接 https www bilibili com video BV1x4411q7Fz 初次录讲解视频 各种差错和画音不同步请各位谅解 我录到后面
  • Qt常用数据类型

    常用数据类型 1 常用基本数据类型 常用接口 求绝对值 T是泛型 以下都是 T qAbs const T t 最大值和最小值 会把最大或最小的返回出来 T qMax const T value1 const T value2 T qMin
  • 解决笔记本电脑(i)某个键的字母按不出来

    前两天清理电脑键盘没有关机然后清理了一下键盘 再使用的时候就打不出 i 字母了 重启也没用 看网上说 使用Fn F11 可以 但是可能每个电脑配置不同 使用失败 最后 想了想F11 不行 最后试试F12吧 最后Fn F11 成功解锁 哈哈哈
  • ffmpeg通过命令拉udp的rtsp流的方法

    ffmpeg用命令拉流是非常简单易用的 特别是对这种常见的摄像头的流 rtsp 10 1 21 121 554 profile1 稍微复杂一点 rtsp admin a1234567 10 1 21 121 554 cam realmoni
  • 【sqli-labs】 less5 GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)...

    双注入查询可以查看这两篇介绍 https www 2cto com article 201302 190763 html https www 2cto com article 201303 192718 html 简而言之就是构造如下的查询
  • 相关性和因果性

    一 如果A和B相关 有至少五种可能性 1 A导致B 2 B导致A 3 C导致A和B 4 A和B互为因果 5 小样本引起的巧合 二 相关是线性关性 非线性的因果关系对应的相关性可能会减弱或消失 统计上A和B具有线性 或者非线性 关系 通常代表
  • AccessibilityEvent常用详解

    AccessibilityEvent常用详解 本文是作者在使用android的AccessibilityService时记录使用到的AccessibilityEvent的一些情况 如有错误欢迎指正 dinjet foxmail com 屏幕
  • C++(VS基础操作)基础操作

    VS的基本操作 1 创建项目在起始页中选择 2 创建文件夹 CPP Project 起文件名称 3 起项目名称 CPPLesson01 4 解决方案 一个解决方案能存放多个项目 一个项目只能选择一个解决方案 5 创建空项目 6 c 使用开发
  • 编译原理(静态语义分析)

    文章目录 语法制导翻译 中间代码简介 后缀式 三地址码 符号表 声明语句的翻译 数组元素的引用 例题 数组元素引用的语法制导翻译 布尔表达式 拉链与回填 语法制导翻译 语义分析的作用 检查结构正确的句子表达的意思是否正确 执行规定的语义动作
  • RHEL6进入救援模式

    1 救援模式 救援模式作用 更改root密码 恢复硬盘 文件系统操作 系统无法启动时 通过救援模式启动 2 放入系统光盘 重启从光盘启动 4 选择语言 默认English就行 5 保持默认即可 6 网口检查 不需要 直接选择NO 7 直接c
  • 函数重载 隐藏 重写 覆盖

    重载 Overload 重载是比较容易弄明白的 定义 重载是指不同的函数使用相同的函数名 但是函数的参数个数或类型不同 参数列表不同 调用的时候根据函数的参数来区别不同的函数 函数重载跟返回值无关 规则 函数名相同 必须具有不同的参数列表
  • 【Linux篇】fputs、fgets函数

    一 fputs函数 include
  • 水下图像采集

    原文 http blog csdn net sunlinyi66 article details 50153875 NASA提供的雾天标准图像 这次终于找到了雾天处理图像来自哪里了 雾天图像 http dragon larc nasa go
  • 机器学习——朴素贝叶斯算法

    朴素贝叶斯算法 1 引言 2 朴素贝叶斯分类方法 3 概率基础 4 朴素贝叶斯特征提取 5 朴素贝叶斯分类的sklearn实现 6 垃圾短息分类 补充 1 引言 贝叶斯方法是一个历史悠久 有着坚实的理论基础的方法 同时处理很多问题时直接而又