基于朴素贝叶斯的垃圾分类算法(Python实现)

2023-11-06

一、模型方法

       本工程采用的模型方法为朴素贝叶斯分类算法,它的核心算法思想基于概率论。我们称之为“朴素”,是因为整个形式化过程只做最原始、最简单的假设。朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示。

        我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中用圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中用三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:

         如果 p1(x,y) > p2(x,y),那么类别为1。

         如果 p2(x,y) > p1(x,y),那么类别为2。

       也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。

在本工程中我们可以使用条件概率来进行分类。其条件概率公式如下:

       其中粗体w表示这是一个向量,它是有多个值组成。对于类别i表示分类的个数,在本工程中i=0时,c0表示非垃圾邮件。i=1时,c1表示垃圾邮件。w展开为一个个独立特征,那么就可以将上述概率写作p(w0,w1,w2..wN|ci)。这里假设所有词都互相独立,该假设也称作条件独立性假设,它意味着可以使用p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)来计算上述概率,这就极大地简化了计算的过程,这也是被称为朴素贝叶斯的原因。在本工程中wj代表第i个单词特征,而p(wj|ci)则代表了在垃圾邮件(或非垃圾邮件)中,第j个单词出现的概率;而p(w|ci)则表示在垃圾邮件(或非垃圾邮件)中的全体向量特征(单词向量特征)出现的概率;而p(ci| w)则表示在全体向量特征(单词向量特征)下是垃圾邮件(或非垃圾邮件)的概率。本工程项目主要是计算p(ci|w)p(ci)则表示是垃圾邮件(或非垃圾邮件)的概率。

二、系统设计

  • 数据的收集及保存

邮件的收集来源于网上,保存在email文件夹中。其中email分两个子文件,一个为ham文件夹(保存非垃圾邮件),另一个为spam文件夹(保存垃圾邮件)。ham与spam中各保存25各邮件,保存格式为x.txt(x为1到25)。

  • 训练集和测试集的选取

由于收集的邮件个数有限,故选取80%的邮件作为训练集,其方式为随机选取。剩余20%邮件作为测试集。

  • 特征向量构建

特征向量的构建分为两种,一个为对训练集的特征向量构建。一个为测试集的特征向量构建。对于训练集特征向量只需要分为两类,因为邮件只分为垃圾邮件和非垃圾邮件。特征向量分为对训练集中所有垃圾邮件中构成的特征向量(记做w)和训练集中所有非垃圾邮件构成特征向量(记做w’)。对于w的计算实际就是统计所有训练集中垃圾邮件中的每个单词的出现情况,出现则次数加1。其计数初值为1,按照正常情况应为0,因为用的朴素贝叶斯算法,假设所有词都互相独立 ,就有p(w|ci) = p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)。所以当第i个单词wi在其特征向量中没有出现,则有p(wi|ci) =0,这就导致了p(w|ci)导致结果的不正确性。所以我们索性将所有单词默认出现1遍,所以从1开始计数。对于w’的计算和w的计算方法相同,这里就不在赘述。

对于测试集的特征向量构建就是对每个邮件中单词出现的次数进行统计,其单词表可以来源于50个邮件中的所有单词。对于每一个邮件中单词如果出现就加1,其计数初值为0。每个测试集的邮件都需构建特征向量。其特征向量在python中可用列表表示。

  • 构建贝叶斯分类器

对于分类器的训练其目的训练三个参数为p1Vect(w中每个单词出现的概率构成的特征向量)、p0Vect(w’中每个单词出现的概率构成的特征向量)和pAbusive(训练集中垃圾邮件的概率)。对于p1Vect、p0Vect计算可能会造成下溢出, p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)时,由于大部分因子都非常小,所以程序会下溢出或者得到不正确的答案。一种解决办法是对乘积取自然对数。在代数中有ln(a*b) = ln(a)+ln(b),于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。图1给出函数f(x)ln(f(x))的曲线。检查这两条曲线,就会发现它们在相同区域内同时增加或者减少,并且在相同点上取到极值。它们的取值虽然不同,但不影响最终结果。

所以p1Vect = log(w/p1Denom),p0Vect = log(w’/p0Denom),其中p1Denom、p0Denom分别为垃圾邮件中单词的总数和非垃圾邮件中单词的总数。而pAbusive 就等于训练集中垃圾邮件总数与训练集中邮件总数之比。

  • 测试集验证与评估

对于判断是否为垃圾邮件,只需对每个邮件判断p(c0|w)(不是垃圾邮件的概率)与p(c1|w)(是垃圾邮件的概率)。

q如果p(c0|w) > p(c1|w),那么该邮件为非垃圾邮件。

q如果 p(c0|w) < p(c1|w),那么该邮件为垃圾邮件。

       然而p(ci|w)(i=0或1)的计算则依赖于p(w|ci)p(ci)的计算,p(w)无需计算。所以最终结果依赖于pi = p(w|ci)·p(ci)。由于p(w|ci)很小,可能向下溢出。所以我们取以10为底的对数得log(pi) = log(p(w|ci))+log(p(ci)),所以可得以下结论:

q如果log(p0) > log(p1),那么该邮件为非垃圾邮件。

q如果log(p0) < log(p1),那么该邮件为垃圾邮件。

其中p(w|ci)为在垃圾邮件(或非垃圾邮件)中的全体向量特征(单词向量特征)出现的概率,p(ci)为训练集中垃圾邮件(或非垃圾邮件)的概率。

三、系统演示与实验结果分析对比

       由训练集(40个)和测试集(个)的样本数目比较小,所以测试的分类结果正确性为90%-100%之间,如下图所示:

        本工程只是对邮件进行二分类,贝叶斯算法也可以处理多分类问题,如新闻的分类,如分成军事、体育、科技等等。当然本工程只是对英文的垃圾邮件分类,但也可以对中文的垃圾邮件分类(可用python中的jieba的库模块进行对中文分词)。

四、代码实现

#coding=UTF-8
import random
from numpy import *

#解析英文文本,并返回列表
def textParse(bigString):
    #将单词以空格划分
    listOfTokens = bigString.split()
    #去除单词长度小于2的无用单词
    return [tok.lower() for tok in listOfTokens if len(tok)>2]

#去列表中重复元素,并以列表形式返回
def createVocaList(dataSet):
    vocabSet = set({})
    #去重复元素,取并集
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)

#统计每一文档(或邮件)在单词表中出现的次数,并以列表形式返回
def setOfWordsToVec(vocabList,inputSet): 
    #创建0向量,其长度为单词量的总数
    returnVec = [0]*len(vocabList)
    #统计相应的词汇出现的数量
    for 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])
    #侮辱性概率(计算p(Ci)),计算垃圾邮件的比率
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    #统计非垃圾邮件中各单词在词数列表中出现的总数(向量形式)
    p0Num = ones(numWords)
    #统计垃圾邮件中各单词在词数列表中出现的总数(向量形式)
    p1Num = ones(numWords)
    #统计非垃圾邮件总单词的总数(数值形式)
    p0Denom = 2.0
    #统计垃圾邮件总单词的总数(数值形式)
    p1Denom = 2.0
    for 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)         
    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 1
    else :
        return 0
#test
def spamtest():
    #导入并解析文本文件
    docList =[];classList=[];fullText = []
    for i in range(1,26):
        #读取第i篇垃圾文件,并以列表形式返回
        wordList = textParse(open('email/spam/{0}.txt'.format(i)).read())
        #转化成二维列表
        docList.append(wordList)
        #一维列表进行追加
        fullText.extend(wordList)
        #标记文档为垃圾文档
        classList.append(1)
        #读取第i篇非垃圾文件,并以列表形式返回
        wordList = textParse(open('email/ham/{0}.txt'.format(i)).read())
        #转化成二维列表
        docList.append(wordList)
        #一维列表进行追加
        fullText.extend(wordList)
        #标记文档为非垃圾文档
        classList.append(0)
    #去除重复的单词元素
    vocabList = createVocaList(docList)
    #训练集,选40篇doc
    trainingSet = [x for x in range(50)]
    #测试集,选10篇doc
    testSet = []
    #选出10篇doc作测试集
    for i in range(10):
        randIndex = int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del trainingSet[randIndex]
    trainMat = [];trainClasses=[]
    #选出40篇doc作训练集
    for docIndex in trainingSet:
        trainMat.append(setOfWordsToVec(vocabList, docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0V,p1V,pSpam = trainNB0(array(trainMat), array(trainClasses))
    #对测试集分类
    errorCount = 0
    for docIndex in testSet:
        wordVector = setOfWordsToVec(vocabList,docList[docIndex])
        if classifyNB(array(wordVector), p0V, p1V, pSpam)!=classList[docIndex]:
            errorCount+=1
    print("错误率为:{0}".format(float(errorCount)/len(testSet)))
spamtest()

 

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

基于朴素贝叶斯的垃圾分类算法(Python实现) 的相关文章

  • 如何替换 Pandas Dataframe 中不在列表中的所有值? [复制]

    这个问题在这里已经有答案了 我有一个值列表 如何替换 Dataframe 列中不在给定值列表中的所有值 例如 gt gt gt df pd DataFrame D ND D garbage columns S gt gt gt df S 0
  • 类的 IPython 表示

    我正在使用我创建的模块尝试 IPython 但它没有显示类对象的实际表示 相反 它显示类似的内容 TheClass module TheClass name I heavily在这个模块中使用元类 我有真正有意义的类表示 应该向用户显示 是
  • Python - 比较同一字典中的值

    我有一本字典 d Trump MAGA FollowTheMoney Clinton dems Clinton Stein FollowTheMoney Atlanta 我想删除字符串列表中的重复字符串 该字符串是键的值 对于这个例子 期望
  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • matplotlib 图中点的标签

    所以这是一个关于已发布的解决方案的问题 我试图在我拥有的 matplotlib 散点图中的点上放置一些数据标签 我试图在这里模仿解决方案 是否有与 MATLAB 的 datacursormode 等效的 matplotlib https s
  • VSCode Settings.json 丢失

    我正在遵循教程 并尝试将 vscode 指向我为 Scrapy 设置的虚拟工作区 但是当我在 VSCode 中打开设置时 工作区设置 选项卡不在 用户设置 选项卡旁边 我还尝试通过以下方式手动转到文件 APPDATA Code User s
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • 为什么 web2py 在启动时崩溃?

    我正在尝试让 web2py 在 Ubuntu 机器上运行 所有文档似乎都表明要在 nix 系统上运行它 您需要下载源代码并执行以下操作 蟒蛇 web2py py 我抓住了source http www web2py com examples
  • 导入错误:没有名为flask.ext.login的模块

    我的flask login 模块有问题 我已经成功安装了flask login模块 另外 从命令提示符我可以轻松运行此脚本 不会出现错误 Python 2 7 r27 82525 Jul 4 2010 07 43 08 MSC v 1500
  • 未知错误:Chrome 无法启动:异常退出

    当我使用 chromedriver 对 Selenium 运行测试时 出现此错误 selenium common exceptions WebDriverException Message unknown error Chrome fail
  • 当字段是数字时怎么说...在 mongodb 中匹配?

    所以我的结果中有一个名为 城市 的字段 结果已损坏 有时它是一个实际名称 有时它是一个数字 以下代码显示所有记录 db zips aggregate project city substr city 0 1 sort city 1 我需要修
  • Pandas 组合不同索引的数据帧

    我有两个数据框df 1 and df 2具有不同的索引和列 但是 有一些索引和列重叠 我创建了一个数据框df索引和列的并集 因此不存在重复的索引或列 我想填写数据框df通过以下方式 for x in df index for y in df
  • Protobuf 如何编码 oneof 消息结构

    对于这个 python 程序 在编码时运行 protobuf 编码会给出以下输出 0a 10 08 7f8a 0104 08 02 10 0392 0104 08 02 10 03 18 01 我不明白的是为什么8a后面有一个01 为什么9
  • PySpark groupByKey 返回 pyspark.resultiterable.ResultIterable

    我试图找出为什么我的 groupByKey 返回以下内容 0
  • 重新分配唯一值 - pandas DataFrame

    我在尝试着assign unique值在pandas df给特定的个人 For the df below Area and Place 会一起弥补unique不同的价值观jobs 这些值将分配给个人 总体目标是使用尽可能少的个人 诀窍在于这
  • 等待子进程使用 os.system

    我用了很多os system在 for 循环内调用创建后台进程 如何等待所有后台进程结束 os wait告诉我没有子进程 ps 我使用的是Solaris 这是我的代码 usr bin python import subprocess imp
  • 根据 Pandas 中的列表选择数据框行的子集

    我有一个数据框df1并列出x In 22 import pandas as pd In 23 df1 pd DataFrame C range 5 B range 10 20 2 A list abcde In 24 df1 Out 24
  • 如何在 Flask 中的视图函数/会话之间传递复杂对象

    我正在编写一个 Web 应用程序 当 且仅当 用户登录时 该应用程序从第三方服务器接收大量数据 这些数据被解析为自定义对象并存储在list 现在 用户在应用程序中使用这些数据 调用不同的视图 例如发送不同的请求 我不确定什么是最好的模式在视
  • JSON:TypeError:Decimal('34.3')不是JSON可序列化的[重复]

    这个问题在这里已经有答案了 我正在运行一个 SQL 查询 它返回一个小数列表 当我尝试将其转换为 JSON 时 出现类型错误 查询 res db execute SELECT CAST SUM r SalesVolume 1000 0 AS
  • 如何在Python脚本中从youtube-dl中提取文件大小?

    我是 python 编程新手 我想在下载之前提取视频 音频大小 任何 YouTube 视频 gt gt gt from youtube dl import YoutubeDL gt gt gt url https www youtube c

随机推荐

  • OpenAI Translator

    简介 OpenAI Translator 一款基于 ChatGPT API 的划词翻译浏览器插件和跨平台桌面端应用 使用 ChatGPT API 进行划词翻译和文本润色 借助了 ChatGPT 强大的翻译能力 帮助用户更流畅地阅读外语和编辑
  • Mac下静态库和动态库的创建和使用

    1 演示代码 add cpp int add int a int b return a b main cpp include
  • js三元表达式

  • Ubuntu13下调试USB AUDIO的一些记录

    最近想玩玩LINUX 于是双系统装了一个Ubuntu13 04 在新系统下用着都还好 不过我自己DIY的USB DAC出了问题 在WIN7下能正常工作 但是在Ubuntu下就爆音不断 很明显是音频数据流断流引起的 这说明stm32上的固件与
  • K8S集群管理

    集群管理 1 集群管理 1 1 节点管理 1 1 1 令牌管理 1 1 2 集群扩缩容 1 1 3 集群升级 1 1 4 证书管理 1 2 数据管理 1 2 1 ETCD基础 1 2 2 ETCD实践 1 2 3 备份还原 1 2 4 ET
  • 4、一维数组、遍历数组、冒泡排序、插入排序、选择排序

    一维数组 定义形式1 数据类型 数组变量名 new 数据类型 数组长度 例1 int array new int 10 例2 char array new char 8 定义形式2 数据类型 数组变量名 值1 值2 值3 值n 例1 int
  • 安装企业版宝塔加美化模版

    宝塔企业7 9 9指令 yum install y wget wget O install sh http jsjs xn n6q058g tk down php 65f0164d0846e99b28c9416a65b66bdd sh sh
  • Storm简介

    场景 伴随着信息科技日新月异的发展 信息呈现出爆发式的膨胀 人们获取信息的途径也更加多样 更加便捷 同时对于信息的时效性要求也越来越高 举个搜索场景中的例子 当一个卖家发布了一条宝贝信息时 他希望的当然是这个宝贝马上就可以被卖家搜索出来 点
  • Redis学习记录(二)

    redis命令 基本命令 心跳命令 ping 读写键值命令 set get DB切换 select 数据库切换 查看数据库中的key数量 dbsize 删除当前库中的数据 flushdb 删除所有库中的数据 flushall 退出客户端命令
  • 【语义分割】DFANet -- Deep Feature Aggregation for Real-Time Semantic Segmentation

    efficient inferrence speed and high accuracy with high resolution Architecture DFANet从整体上可看做是encoder decoder结构 包括四个部分 th
  • sklearn中的XGBClassifier参数详解

    前言 1 Xgboost简介 Xgboost是Boosting算法的其中一种 Boosting算法的思想是将许多弱分类器集成在一起 形成一个强分类器 因为Xgboost是一种提升树模型 所以它是将许多树模型集成在一起 形成一个很强的分类器
  • Linux内核模块管理(查看、添加和删除)

    Linux 的内核会在启动过程中自动检验和加载硬件与文件系统的驱动 一般这些驱动都是用模块的形式加载的 使用模块的形式保存驱动 可以不直接把驱动放入内核 有利于控制内核大小 模块的全称是动态可加载内核模块 它是具有独立功能的程序 可以被单独
  • Java多线程问题--wait()和notify()

    本文内容部分引自 Java多线程编程核心技术 感谢作者 代码地址 https github com xianzhixianzhixian thread git 介绍wait 和notify 的使用以及注意事项 1 wait 方法是Objec
  • 图像相似度的评价指标 : FID(Fréchet Inception Distance)

    FID Fr chet Inception Distance 是用来计算真实图像与生成图像的特征向量间距离的一种度量 如果FID值越小 则相似程度越高 最好情况即是FID 0 两个图像相同 实际计算 参考链接 https machinele
  • 一个石头剪刀布游戏的python解法

    一个石头剪刀布的python解法 import random game 石头 剪刀 布 随机生成一个1 3之间的数 random digit random randint 1 3 输入你猜测的数 num int input 请输入1 2 3
  • RHEL5.6 下安装并测试openCV1.0.0(----成功----)

    一 首先去openCV官网下载openCV1 0 0版本 貌似需要翻墙后才能下载 二 解压源码包并安装 configure without python enable shared prefix opt opencv make make i
  • C++ 多线程 报错invalid use of non-static member function

    创建一个类test class test public void func std cout lt lt test main函数多线程调用test test t new test std thread th t gt func 编译报错 G
  • visual studio用环境变量设置目录

    visual studio里可以用环境变量来指定包含目录等目录
  • 程序的动态特性

    程序的动态特性 大多数情况下 程序的功能是在编译的时候确定下来的 称之为静态特性 而如果程序的功能是在运行时才确定的称为动态特性 动态特性是面向对象语言最强大的功能之一 它在语言层面上支持程序的可扩展性 动态特性 由C 虚函数 抽象基类 动
  • 基于朴素贝叶斯的垃圾分类算法(Python实现)

    一 模型方法 本工程采用的模型方法为朴素贝叶斯分类算法 它的核心算法思想基于概率论 我们称之为 朴素 是因为整个形式化过程只做最原始 最简单的假设 朴素贝叶斯是贝叶斯决策理论的一部分 所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论