【机器学习实战】朴素贝叶斯:过滤垃圾邮件

news/2024/5/9 22:44:14/文章来源:https://blog.csdn.net/RangeLZ/article/details/132393757

【机器学习实战】朴素贝叶斯:过滤垃圾邮件

0.收集数据

这里采用的数据集是《机器学习实战》提供的邮件文件,该文件有hamspam 两个文件夹,每个文件夹中各有25条邮件,分别代表着 正常邮件垃圾邮件

这里需要注意的是需要将 email 文件夹放在 py 代码文件同一级的地方。若放在其他地方,需要修改博主代码中的相对地址才可正常执行。
在这里插入图片描述

1.解析数据

我们需要将我们的文本文件导入到程序里面,其中主要参数如下:

  • d o c L i s t : docList: docList 是一个二维数组,一共记录了50封邮件的内容。
  • f u l l T e x t : fullText: fullText是50封邮件中出现的所有单词的一个大的单词列表(有重复单词)
  • c l a s s L i s t : classList: classList用于记录当前邮件是 正常邮件 还是 垃圾邮件01 进行区分。
  • v o c a b L i s t : vocabList : vocabList是一个单词均不重复的词汇表。
# 导入并解析文本文件for i in range(1, 26):  # 因为每个文件夹各有文件25个wordList = textParse(open('email/spam/%d.txt' % i, encoding="ISO-8859-1").read())  # 读取文件docList.append(wordList)  # 用于存储所有文件的单词列表,二维数组fullText.extend(wordList)  # 这个列表用于存储所有文件的单词,将它们合并成一个大的单词列表classList.append(1)wordList = textParse(open('email/ham/%d.txt' % i, encoding="ISO-8859-1").read())docList.append(wordList)fullText.extend(wordList)classList.append(0)vocabList = createVocabList(docList)  # 创建不重复的词汇表# 邮件裁词
def textParse(bigString):regEx = re.compile(r'\W')listOfTokens = regEx.split(bigString)var = [tok.lower() for tok in listOfTokens if len(tok) > 2]  # 只返回长度大于2的情况return var# 创建词汇表
def createVocabList(dataSet):vocabSet = set([])  # 创建一个无序且不重复的集合对象for document in dataSet:vocabSet = vocabSet | set(document)  # 创建两个集合的并集return list(vocabSet)

ps:因为这里的邮件全是英文邮件,所以读取的时候编码是 encoding="ISO-8859-1"

2.区分“测试集”和“训练集”

这里我们一共创建了10个测试集,每取一个测试集就将其的索引从trainingSet 中删除。故trainingSet 最后剩下的40个索引就是训练集,testSet中的10个索引就是测试集。

  • 测试集:用于判断朴素贝叶斯分类是否有问题。
  • 训练集:用于训练朴素贝叶斯分类器的参数。
	trainingSet = list(range(50))  # 训练集的索引,0-49(因为ham和spam各有25个,故一共有50个)trainingSet = trainingSettestSet = []# 随机构造训练集for i in range(10):  # 表示只创建10个测试集、剩下的都是训练集# 函数生成一个0到len(trainingSet)之间的随机浮点数,然后取整,得到一个随机的索引值randIndex。randIndex = int(random.uniform(0, len(trainingSet)))testSet.append(trainingSet[randIndex])  # 将随机选择的索引值randIndex添加到测试集列表testSet中。trainingSet.pop(randIndex)  # 删除训练集中对应的测试集的索引值,以确保不会重复选择作为测试集。

3.训练算法

朴素贝叶斯算法往简单说,就是计算出当前参数为不同情况的概率,最后哪个可能性的概率大,那么他就是哪一类。

3.1 统计词汇出现的次数

# 朴素贝叶斯词袋模型
def bagOfWords2VecMN(vocabList, inputSet):returnVec = [0] * len(vocabList)  # 创建一个长度为vocabList的列表returnVec,并将列表中的每个元素都初始化为0for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1  # 在词库里出现次数return returnVec

3.2.训练函数

将各个邮件中词汇出现次数的词袋,和最初记录每个邮件是 正常邮件 还是 垃圾邮件 的列表传入trainNB0计算出每个词汇是正常还是垃圾的可能性。

# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):numTrainDocs = len(trainMatrix)numWords = len(trainMatrix[0])pAbusive = sum(trainCategory) / float(numTrainDocs)  # 侮辱性单词出现的概率p0Num = ones(numWords)  # 为了防止出现 0 * x 的情况p1Num = ones(numWords)p0Denom = 2.0  # 为了防止分母为0的情况p1Denom = 2.0for i in range(numTrainDocs):if trainCategory[i] == 1:p1Num += trainMatrix[i]  # 计算每个词出现的次数p1Denom += sum(trainMatrix[i])  # 计算总共出现多少个词else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = log(p1Num / p1Denom)  # 计算每个词语是侮辱性词汇的概率p0Vect = log(p0Num / p0Denom)  # log是为了防止数据太小导致下溢出return p0Vect, p1Vect, pAbusive

3.3分类器

根据我们确定的计算概率公式,计算出它各个分类的可能性然后进行比较,返回我们最好的决定。

# 朴素贝叶斯分类函数
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 0

4.完整代码

import re
from numpy import *# 创建词汇表
def createVocabList(dataSet):vocabSet = set([])  # 创建一个无序且不重复的集合对象for document in dataSet:vocabSet = vocabSet | set(document)  # 创建两个集合的并集return list(vocabSet)# 朴素贝叶斯词袋模型 setOfWords2Vec 升级版本
def bagOfWords2VecMN(vocabList, inputSet):returnVec = [0] * len(vocabList)  # 创建一个长度为vocabList的列表returnVec,并将列表中的每个元素都初始化为0for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1  # 在词库里出现次数return returnVec# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):numTrainDocs = len(trainMatrix)numWords = len(trainMatrix[0])pAbusive = sum(trainCategory) / float(numTrainDocs)  # 侮辱性单词出现的概率p0Num = ones(numWords)  # 为了防止出现 0 * x 的情况p1Num = ones(numWords)p0Denom = 2.0  # 为了防止分母为0的情况p1Denom = 2.0for i in range(numTrainDocs):if trainCategory[i] == 1:p1Num += trainMatrix[i]  # 计算每个词出现的次数p1Denom += sum(trainMatrix[i])  # 计算总共出现多少个词else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = log(p1Num / p1Denom)  # 计算每个词语是侮辱性词汇的概率p0Vect = log(p0Num / p0Denom)  # log是为了防止数据太小导致下溢出return p0Vect, p1Vect, pAbusive# 朴素贝叶斯分类函数
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 0# 邮件裁词
def textParse(bigString):regEx = re.compile(r'\W')listOfTokens = regEx.split(bigString)var = [tok.lower() for tok in listOfTokens if len(tok) > 2]  # 只返回长度大于2的情况return vardef spamTest():docList = []classList = []fullText = []# 导入并解析文本文件for i in range(1, 26):  # 因为每个文件夹各有文件25个wordList = textParse(open('email/spam/%d.txt' % i, encoding="ISO-8859-1").read())  # 读取文件docList.append(wordList)  # 用于存储所有文件的单词列表,二维数组fullText.extend(wordList)  # 这个列表用于存储所有文件的单词,将它们合并成一个大的单词列表classList.append(1)wordList = textParse(open('email/ham/%d.txt' % i, encoding="ISO-8859-1").read())docList.append(wordList)fullText.extend(wordList)classList.append(0)vocabList = createVocabList(docList)  # 创建不重复的词汇表trainingSet = list(range(50))  # 训练集的索引,0-49(因为ham和spam各有25个,故一共有50个)trainingSet = trainingSettestSet = []# 随机构造训练集for i in range(10):  # 表示只创建10个测试集、剩下的都是训练集# 函数生成一个0到len(trainingSet)之间的随机浮点数,然后取整,得到一个随机的索引值randIndex。randIndex = int(random.uniform(0, len(trainingSet)))testSet.append(trainingSet[randIndex])  # 将随机选择的索引值randIndex添加到测试集列表testSet中。trainingSet.pop(randIndex)  # 删除训练集中对应的测试集的索引值,以确保不会重复选择作为测试集。trainMat = []trainClasses = []for docIndex in trainingSet:# 将选中的训练集索引的文本,和词汇表进行对比计算词汇出现的次数trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))trainClasses.append(classList[docIndex])  # 将文档的类别标签添加到trainClasses列表中# 调用trainNB0函数,传入训练数据的特征向量和类别标签,进行朴素贝叶斯训练,得到分类器的参数p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))errorCount = 0  # 计算错误次数,初始值为0# 对测试集分类for docIndex in testSet:wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])  # 计算出现次数if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:  # 计算结果并判断是否判断正确errorCount += 1print("classification error", docList[docIndex])print('the error rate is: ', float(errorCount) / len(testSet))if __name__ == '__main__':spamTest()

结果截图:
在这里插入图片描述

5.总结

个人感觉该方法的分类准确率,对准备的数据以及概率计算方法很敏感,可能一点点的改变就会导致最后的统计结果天差地别。总的来说,朴素贝叶斯并不难,代码也相对比较好理解,这一章就顺利通过啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_159119.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝牙 - BLE SPP的设计策略(Serial over BLE strategy)

在开发 BLE 连接产品的过程中,你可能会有这样的疑问:"Serial profile在哪里?也许你以为你在蓝牙技术联盟网站上滚动浏览长长的profile列表时错过了它。又或者,你根本就没去看,而是准备选择更快的方法,…

人脸识别技术在社会安全与便利中的应用

引言:随着人工智能的快速发展,人脸识别技术已经成为一种实时、高效的身份验证和安全监控手段。它的广泛应用可以帮助识别犯罪嫌疑人、寻找失踪人口等,为社会安全和公共利益做出了重要贡献。本文将详细探讨人脸识别技术的原理、应用&#xff0…

【高级IO】- 五种 IO 模型 | 多路转接 - select

IO的基本概念 I/O(Input / output)就是输入和输出,在冯诺依曼体系中,将数据从输入设备拷贝到内存叫做输入,将数据从内存拷贝到输出设备叫做输出。 对文件进行的读写操作本质就是一种IO,文件IO对应的外设就…

Linux命令200例:clock的具体应用,设置系统的时钟时间、硬件时钟和定时器等相关信息

🏆作者简介,黑夜开发者,全栈领域新星创作者✌。CSDN专家博主,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 &…

前端对文件转换处理的一些常用方法

文章目录 0,前言1,将图片的url网络链接(http://) 转为base64格式2,将base64的图片数据转换为file文件3,将以base64的图片数据转换为Blob4,将file文件转化为base645,将file文件转换为Blob6,获取文…

微信公众平台发布小程序流程

最近因为部署小程序,学习了下如何部署小程序 1. 取消不检验合法域名并上传小程序 建议在小程序上传之前,先取消不校验合法域名并真机调试下。 2. 登录微信公众平台 登录微信公众平台 3. 设置服务器域名 在开放->开发管理->开发设置找到服务器…

三维重建_基于图像的三维重建_面片/光度一致性

参考: 深蓝学院 基于图像的三维重建 1. 三维重建的流程回顾 基于深度图的三维重建:从无序图像获取稀疏点云和位姿,然后进行多视角立体重建。 多视角立体重建包含:(输入稀疏点云、各个图像位姿、图像)先进行立体对(3D-2D,2D-2D)的选择,然后计算深度图,接着进行深度图…

【C语言】C语言用数组算平均数,并输出大于平均数的数

题目 让用户输入一系列的正整数&#xff0c;最后输入“-1”表示输入结束&#xff0c;然后程序计算出这些数的平均数&#xff0c;最后输出输入数字的个数和平均数以及大于平均数的数 代码 #include<stdio.h> int main() {int x;double sum 0;int cnt 0;int number[100…

使用 AI 将绘画和照片转换为动画

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑器的3D应用场景 华盛顿大学和Facebook的研究人员最近发表了一篇论文&#xff0c;展示了一种基于深度学习的系统&#xff0c;可以将静止图像和绘画转换为动画。称为照片唤醒的算法使用卷积神经网络从单个静止图像以 …

WPF入门到精通:1.新建项目及项目结构

WPF&#xff08;Windows Presentation Foundation&#xff09;是一种用于创建 Windows 应用程序的技术&#xff0c;它可以通过 XAML&#xff08;Extensible Application Markup Language&#xff09;和 C# 或其他 .NET 语言来实现。WPF 提供了许多强大的 UI 控件和样式&#xf…

如何找到一个数的所有质因数,以及如何快速判断一个数是不是质数

前情介绍 今天遇到一个需求&#xff1a;找到一个数所有的质因数。 初步解决 先定义一个判断质数的函数&#xff1a; def is_Prime(number):i 2count 0while i < number:if number % i 0 :count 1i 1if count > 0:return Falseelse:return True 接着定义一个寻找质…

Java-图书登录系统的实现

实现效果 它将面对 管理员 和 普通用户 两种用户来提供服务&#xff0c;并且各自的服务并不相同。 实现思路 一般写项目&#xff0c;每个独立的功能都会写成一个类&#xff0c;而有关联的功能&#xff0c;都会将多个类存放在一个包中&#xff0c;此项目我们将用 3 个包来体现我…

链表之第三回

欢迎来到我的&#xff1a;世界 该文章收入栏目&#xff1a;链表 希望作者的文章对你有所帮助&#xff0c;有不足的地方还请指正&#xff0c;大家一起学习交流 ! 目录 前言第一题&#xff1a;判断是否为环形链表第二题&#xff1a;找到两条链表的相交点第三题&#xff1a;返回…

P17~P18 电路定理 电路中难得的精彩到极致的电路理论

特勒根定理、互易定理、对偶定理比较难&#xff0c;非常重要&#xff0c;因为他们可以解决其他定理无法解决的问题。 1、特勒根定理1——个人感觉像能量守恒 特勒根定理与基尔霍夫定理齐名&#xff0c;与拓扑结构有关。都适用于任何线性非线性&#xff0c;时变的非时变的元件…

分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测

分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测 目录 分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测 程序设计 完整源码和数据获取方式&#xff1a; …

网站老域名跳转到新域名有哪些方法?内网穿透内网主机让外网访问

在网站服务器变更及本地主机搭建时&#xff0c;我们经常会遇到老域名地址跳转到新URL的配置&#xff0c;一些朋友还会面对无公网IP让外网访问的问题。今天我们来了解下网站老域名跳转到新域名有哪些方法&#xff0c;以及如何通过内网穿透实现内网主机让外网访问。 网站老域名跳…

Mac上传项目源代码到GitHub的修改更新

Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github&#xff0c;不得不说&#xff0c;真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先&#xff0c;在本地终端命令行打开至项目文件下第一步&#xff1a;查看当前的git仓库状态&#xff0c;可以使用git…

线上异常的处理

一、线上问题的排查 进程ID 简称为PID free -m 查看内存使用情况 iostat 查看磁盘读写活动情况 netstat 查看网络连接情况 df -h 查看磁盘空间使用情况 du -sh 查看文件大小情况 1.1、top 命令查看CPU占用情况 top -n num 查看CPU占用最高的num个进程top -Hp PID 或 top -H -p…

【ROS】参数服务器--理论模型与参数操作(C++)

一、概念介绍 参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点也可以往其中存储数据。 作用&#xff1a;存储一些多节点…

【MySQL系列】SQL语句入门(创建删除操作)、字符集和数据类型详解

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …