【Python机器学习】朴素贝叶斯——使用Python进行文本分类
目录
准备文本:从文本中构建词向量
训练算法:从词向量计算概率
测试算法:根据现实情况修改分类器
准备数据:文档词袋模型
要从文本中获取特征,需要先拆分文本。这里的特征是来自文本的词条,一个词条是字符的任意组合。可以把词条想象为单词,也可以使用非单词词条,如URL、IP地址或者任意其他字符串。然后将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文本中,0表示词条未出现。
以社区的留言板为例。为了不影响社区的发展,我们要屏蔽侮辱性的言论,所以要构建一个快速过滤器,如果发现某条留言使用了负面或者侮辱性的语言,那么就将该留言标识为内容不当。过滤这类内容是一个很常见的需求。对此问题建立两个类别:侮辱性和非侮辱性,使用1和0分别表示。
下面是将文本转换为数字向量的过程,然后基于这些向量来计算条件概率,并在此基础上构建分类器,最后是一些利用Python实现朴素贝叶斯过程中需要考虑的问题。
准备文本:从文本中构建词向量
我们将把文本看成单词向量或者词条向量,也就是说将句子转换成向量。考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表或者说所要的词汇集合,然后必须要将每一篇文档转换成词汇表上的向量。
def loadDataSet():postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],['stop', 'posting', 'stupid', 'worthless', 'garbage'],['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]classVec = [0,1,0,1,0,1] #1 is abusive, 0 notreturn postingList,classVecdef createVocabList(dataSet):#创建一个空集vocabSet=set([])for document in dataSet:#创建两个集合的并集vocabSet=vocabSet|set(document)return list(vocabSet)def setOfWords2Vec(vocabList,inputSet):#创建一个其中包含元素都是0的向量returnVec=[0]*len(vocabList)for word in inputSet:if word in vocabList:#如果词汇出现在词汇表中,向量对应值为1,否则为0returnVec[vocabList.index(word)]=1else:print('%s 这个单词不在词汇表中!')return returnVec
上述代码中,第一个函数loadDataSet()创建了一些实验样本。该函数返回的第一个变量是进行词条切割后的文档集合,这些文档来自够累爱好者留言板。这些留言文本被切分成一系列的此条集合,标点符号从文本中去掉。loadDataSet()返回的第二个变量是一个类别标签的集合。这里有两类:侮辱性和非侮辱性。这些文本的类别由人工标注,这些标注信息用于训练程序一遍自动检测侮辱性留言。
createVocabList(dataSet)会创建一个包含在所有文档中出现的不重复词的列表,为此使用了Python的set数据类型。将词条列表输给set构造函数,set就会返回一个不重复词表。
获得词表后,使用setOfWords2Vec(vocabList,inputSet),该函数的输入参数为词汇表及某个文档,输出的是文档向量,向量的每一元素为1或0,分别表示词汇表中的单词在输入文档中是否出现。
观察效果:
listOPosts,listClasses=loadDataSet()
myVocabList=createVocabList(listOPosts)
print(myVocabList)

检查词表,可以看到这里没有重复的单词。
看下setOfWords2Vec()效果:
print(setOfWords2Vec(myVocabList,listOPosts[0]))
print(setOfWords2Vec(myVocabList,listOPosts[3]))

训练算法:从词向量计算概率
上面是将一组单词转换为数字的过程,接下来看如何使用数字计算概率。
现在已经知道一个词是否出现在一篇文档中,也知道该文档所属的类别,我们就可以计算贝叶斯公式:
我们使用上述公式,对每个类计算该值,然后比较这两个概率值的大小。首先可以通过类别i(侮辱性留言或非侮辱性留言)中文档数除以总的文档数来计算概率。接下来计算
,这里就要用到朴素贝叶斯假设。如果将w展开为一个个独立特征,那么就可以将上述概率写作
。这里假设所有词都相互独立,该假设也称为条件独立性假设,它意味着可以使用
来计算上述概率,这就极大地简化了计算过程。
函数的伪代码如下:
计算每个类别中的文档数目
对每篇训练文档:
对每个类别:
如果词条出现在文档中->增加该词条的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目除以总词条数目得到条件概率
返回每个类别的条件概率
下面,开始实现上述伪代码:
def trainNBO(trainMatrix,trainCategory):numTrainDocs=len(trainMatrix)numWords=len(trainMatrix[0])pAbusive=sum(trainCategory)/float(numTrainDocs)#初始化概率p0Num=zeros(numWords)p1Num=zeros(numWords)p0Denom=0.0p1Denom=0.0#对每篇训练文档for i in range(numTrainDocs):#如果词条出现在文档中if trainCategory[i]==1:p1Num=p1Num+trainMatrix[i]p1Denom=p1Denom+sum(trainMatrix[i])else:p0Num=p0Num+trainMatrix[i]p0Denom=p0Denom+sum(trainMatrix[i])#对每个元素做除法p1Vect=p1Num/p1Denomp0Vect=p0Num/p0Denomreturn p0Vect,p1Vect,pAbusive
代码函数中的输入参数为文档矩阵trainMatrix以及由每篇文档类别标签所构成的向量trainCategory。首先,计算文档属于侮辱性文档(class=1)的概率,即P(1)。因为这是一个二类分类问题,所以可以通过1-P(1)得到P(0)。对于多分类问题,则需要对代码进行修改。
计算和
,需要初始化程序中的分子变量和分母变量。由于w中元素非常多,因此可以使用NumPy数组快速计算这些值。分母变量是一个元素个数等于词汇表大小的NumPy素组。在gor循环中,要遍历训练集trainMatrix中所有的文档。一旦某个词语(侮辱性或者正常词语)在某一文档出现,则该词对应的个数(p1Num或者p0Num)就加一。而且在所有的文档中,该文档的总次数也相应加一。对于两个类别都要进行同样的处理。
最后,对每个元素除以该类别中的总次数。利用NumPy很好实现,用一个数组除以浮点数即可,最后函数会返回两个向量和一个概率。
运行:
listOPosts,listClasses=loadDataSet()
myVocabList=createVocabList(listOPosts)
trainMat=[]
for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
p0V,p1V,pAb=trainNBO(trainMat,listClasses)
print(pAb)
print(p0V)

这就是任意文档属于侮辱性文档的概率。
我们发现文档属于侮辱性文档的概率pAb为0.5。下面是给定文档类别条件下词汇表中单词出现的频率。
测试算法:根据现实情况修改分类器
利用贝叶斯 分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,即计算。如果其中一个概率值为0,那么最后的乘积也为0.为降低这种影响,可以将所有词的出现初始化为1,并将分母初始化为2.
修改代码:
p0Num=ones(numWords)p1Num=ones(numWords)p0Denom=2.0p1Denom=2.0
另一个问题是下溢出,这是由于太多很小的数相乘造成的。当计算乘积时,由于大部分因子都非常小,所以程序会下溢出或者得到不正确的答案。一种解决办法是对乘积取自然对数。在代数中有ln(a*b)=ln(a)+ln(b),于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。
修改代码:
p1Vect=log(p1Num/p1Denom)p0Vect=log(p0Num/p0Denom)
现在已经准备好构造完整的分类器了。当使用NumPy向量处理功能时,这会十分简单:
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):#元素相乘p1=sum(vec2Classify*p1Vec)+log(pClass1)p0=sum(vec2Classify*p0Vec)+log(1.0-pClass1)if p1>p0:return 1else:return 0def testingNB():listOPosts,listClasses=loadDataSet()myVocabList=createVocabList(listOPosts)trainMat=[]for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))p0V, p1V, pAb = trainNBO(trainMat, listClasses)testEntry=['love','my','dalmation']thisDoc=array(setOfWords2Vec(myVocabList,testEntry))print(testEntry,'classified as :',classifyNB(thisDoc,p0V,p1V,pAb))testEntry=['stupid','garbage']thisDoc=array(setOfWords2Vec(myVocabList,testEntry))print(testEntry,'classified as :',classifyNB(thisDoc,p0V,p1V,pAb))
classifyNB()函数有4个输入参数:要分类的向量vec2Classify,以及使用函数trainNB0()计算得到的三个概率值。使用NumPy的数组来计算两个向量相乘的结果。这里的相乘是指对应元素相乘,即先将两个向量中的第一个元素相乘,然后将第二个元素相乘,以此类推。接下来将词汇表中所有词的对应值相加,然后将该值加到类别的对数概率上。最后,比较类别的概率返回大概率对应的类别标签。
代码的第二个函数是一个便利函数,该函数封装所有操作,以节省时间。
运行结果:

上述例子展示了朴素贝叶斯分类器的工作原理。
准备数据:文档词袋模型
我们将每个词的出现与否作为一个特征,这可以被表述了词集模型。如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型。在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。为了适应词袋模型,需要对上面的setOfWords2Vec()稍作修改,修改后的函数称为bagOfWords2Vec()。
def bagOfWords2Vec(vocabList,inputSet):#创建一个其中包含元素都是0的向量returnVec=[0]*len(vocabList)for word in inputSet:if word in vocabList:#如果词汇出现在词汇表中,向量加1returnVec[vocabList.index(word)]=returnVec[vocabList.index(word)]+1return returnVec
相关文章:
【Python机器学习】朴素贝叶斯——使用Python进行文本分类
目录 准备文本:从文本中构建词向量 训练算法:从词向量计算概率 测试算法:根据现实情况修改分类器 准备数据:文档词袋模型 要从文本中获取特征,需要先拆分文本。这里的特征是来自文本的词条,一个词条是字…...
【linux】Shell脚本三剑客之grep和egrep命令的详细用法攻略
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...
Spring条件装配:灵活配置你的应用
文章目录 摘要1. 条件装配概述1.1 什么是条件装配1.2 为什么需要条件装配 2. 使用Conditional注解2.1 Conditional注解简介2.2 编写自定义条件类2.3 应用Conditional注解 3. 内置的条件注解3.1 ConditionalOnClass3.2 ConditionalOnMissingBean3.3 ConditionalOnProperty 4. 使…...
【前端 08】简单学习js字符串
JavaScript中的String对象详解 在JavaScript中,字符串(String)是一种非常基础且常用的数据类型,用于表示文本数据。虽然JavaScript中的字符串是原始数据类型,但它们的行为类似于对象,因为JavaScript为字符…...
【LLM】-07-提示工程-聊天机器人
目录 1、给定身份 1.1、基础代码 1.2、聊天机器人 2、构建上下文 3、订餐机器人 3.1、窗口可视化 3.2、构建机器人 3.3、创建JSON摘要 利用会话形式,与具有个性化特性(或专门为特定任务或行为设计)的聊天机器人进行深度对话。 在 Ch…...
AvaloniaUI的学习
相关网站 github:https://github.com/AvaloniaUI/Avalonia 官方中文文档:https://docs.avaloniaui.net/zh-Hans/docs/welcome IDE选择 VS2022VSCodeRider 以上三种我都尝试过,体验Rider最好。VS2022的提示功能不好,VSCode太慢,…...
刷题——快速排序
【全网最清晰快速排序,看完快排思想和代码全部通透,不通透你打我!-哔哩哔哩】 https://b23.tv/8GxEKIk 代码详解如上 #include <iostream> using namespace std;int getPort(int* a, int low, int high) {int port a[low];while(low…...
VPN,实时数据显示,多线程,pip,venv
VPN和翻墙在本质上是不同的。想要真正实现翻墙,需要选择部署在墙外的VPN服务。VPN也能隐藏用户的真实IP地址 要实现Python对网页数据的定时实时采集和输出,可以使用Python的定时任务调度模块。其中一个常用的库是APScheduler。您可以编写一个函数&#…...
自然语言处理(NLP)
自然语言处理(NLP)是计算机科学与人工智能领域的一个重要研究方向,它致力于让计算机能够理解、分析、处理和生成人类语言。在NLP领域,存在着许多常见的任务,这些任务通常对应着不同的算法和技术。以下将详细列举几个NL…...
Spring Boot集成Spire.doc实现对word的操作
1.什么是spire.doc? Spire.Doc for Java 是一款专业的 Java Word 组件,开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件,Spire.Doc for Java 的运行环境无需安装 Micro…...
在Spring Boot中优化if-else语句
在Spring Boot中,优化if-else语句是提升代码质量、增强可读性和可维护性的重要手段。过多的if-else语句不仅会使代码变得复杂难懂,还可能导致代码难以扩展和维护。以下将介绍七种在Spring Boot中优化if-else语句的实战方法,每种方法都将结合示…...
【Django】开源前端库bootstrap,常用
文章目录 下载bootstrap源文件到本地项目引入bootstrap文件 官网:https://www.bootcss.com/V4版本入口:https://v4.bootcss.com/V5版本入口:https://v5.bootcss.com/ 这里使用成熟的V4版本,中文文档地址:https://v4.b…...
2024后端开发面试题总结
一、前言 上一篇离职贴发布之后仿佛登上了热门,就连曾经阿里的师兄都看到了我的分享,这波流量真是受宠若惊! 回到正题,文章火之后,一些同学急切想要让我分享一下面试内容,回忆了几个晚上顺便总结一下&#…...
opencascade AIS_Manipulator源码学习
前言 AIS_Manipulator 是 OpenCASCADE 库中的一个类,用于在3D空间中对其他交互对象或一组对象进行局部变换。该类提供了直观的操控方式,使用户可以通过鼠标进行平移、缩放和旋转等操作。 详细功能 交互对象类,通过鼠标操控另一个交互对象…...
Hadoop、Hive、HBase、数据集成、Scala阶段测试
姓名: 总分:Hadoop、Hive、HBase、数据集成、Scala阶段测试 一、选择题(共20道,每道0.5分) 1、下面哪个程序负责HDFS数据存储( C ) A. NameNode B. Jobtracher C. DataNode D. Sec…...
go语言day19 使用git上传包文件到github Gin框架入门
git分布式版本控制系统_git切换head指针-CSDN博客 获取请求参数并和struct结构体绑定_哔哩哔哩_bilibili (gin框架) GO: 引入GIn框架_go 引入 gin-CSDN博客 使用git上传包文件 1)创建一个github账户,进入Repositories个人仓…...
Ubuntu升级软件或系统
Ubuntu升级软件或系统 升级Ubuntu系统通常是一个相对简单的过程,但在进行操作之前,请务必备份重要数据以防万一。下面是升级Ubuntu系统的一般步骤: 使用软件更新工具升级系统 打开终端: 按下 Ctrl Alt T 组合键打开终端。 更…...
【Redis】Centos7 安装 redis(详细教程)
查看当前 Redis 版本: 当前的 redis 版本太老了,选择安装 Redis5。 一、使用 yum 安装 1、首先安装 scl 源 yum install centos-release-scl-rh 由于我之前已经安装过了,所以加载速度比较快,且显示已经安装成功,是最…...
Hakuin:一款自动化SQL盲注(BSQLI)安全检测工具
关于Hakuin Hakuin是一款功能强大的SQL盲注漏洞安全检测工具,该工具专门针对BSQLi设计,可以帮助广大研究人员优化BSQLi测试用例,并以自动化的形式完成针对目标Web应用程序的漏洞扫描与检测任务。 该工具允许用户以轻松高效的形式对目标Web应…...
在 Postman 中设置全局 token
目录 问题描述解决方案 问题描述 在使用 Postman 进行接口测试时,经常会遇到在 Header 中添加 token 的情况。当接口数量较多时,需要为每个接口进行设置,而且当 token 失效时需要重新获取并设置,这样一来效率较低。 解决方案 下…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
