一.基于贝叶斯决策理论的分类方法

朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法。对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同。比如决策树,KNN,逻辑回归,支持向量机等,他们都是判别方法,也就是直接学习出特征输出Y和特征X之间的关系,要么是决策函数,要么是条件分布。但是朴素贝叶斯却是生成方法,该算法原理简单,也易于实现。

优点:在数据较少的情况下仍然有效,可以处理多类别问题。

缺点:对于输入数据的准备方式较为敏感。

适用数据类型:标称型数据

朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。  假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示:

我们现在用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。
        也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有 最高概率的决策。看图1,如果该图中的整个数据使用6个浮点数来表示,并且计算类别概率的Python代码只有两行,那么我们应该使用下面哪种方法来对该数据点进行分类?

使用kNN算法,则需要进行1000次距离计算,和简单的概率计算相比,kNN的计算量太大;
使用决策树,则需要分别沿x轴、y轴划分数据,似乎效果并不是很好;
还有就是计算数据点属于每个类别的概率,并进行比较,这是最佳选择。

使用朴素贝叶斯过滤垃圾邮件

使用朴素贝叶斯进行交叉验证

def textParse(bigString):  # 输入字符串, 输出单词列表import relistOfTokens = re.split(r'[\W*]', bigString)                    # 字符串切分,去掉除单词、数字外的任意字符串return [tok.lower() for tok in listOfTokens if len(tok) > 2]    # 除了单个字母外,其他字符串全部转换成小写

函数textParse()接受一个大字符串并将其解析为字符串列表。该函数去掉少于两个字符的字符串,并将所有字符串转换为小写。

# 完整的垃圾邮件测试函数
def spamTest():docList = []                 # 文档列表classList = []               # 文档标签fullText = []                # 全部文档内容集合for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个wordList = textParse(open('email/spam/%d.txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件wordList = textParse(open('email/ham/%d.txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 非垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,vocabList = createVocabList(docList)                             # 创建不重复的词汇表trainingSet = list(range(50))                                    # 为训练集添加索引testSet = []                                                     # 创建测试集for i in range(10):                                              # 目的为了从50个邮件中,随机挑选出40个作为训练集,10个做测试集randIndex = int(random.uniform(0, len(trainingSet)))         # 随机产生索引testSet.append(trainingSet[randIndex])                       # 添加测试集的索引值del (trainingSet[randIndex])                                 # 在训练集中,把加入测试集的索引删除trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量trainClasses = []                                                # 训练集类别标签for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表ttrainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数print('词表:\n', vocabList)print('p0V:\n', p0V)print('p1V:\n', p1V)print('pSpam:\n', pSpam)errorCount = 0                                                   # 用于计数错误分类for docIndex in testSet:                                         # 循环遍历训练集wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])  # 获得测试集的词集模型if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:errorCount += 1                                          # 预测值和真值不一致,则错误分类计数加1print("分类错误集", docList[docIndex])print('错误率: ', float(errorCount) / len(testSet))

函数spamTest()对贝叶斯垃圾邮件分类器进行自动化处理。导入文件夹spam与ham下的文本文件,并将它们解析为词列表 。

接下来构建一个测试集与一个训练集,两个集合中的 邮件都是随机选出的。有50封电子邮件,并不是很多,其中的10封电子邮件被随机选择为测试集。分类器所需要的概率计算只利用训练集中的文档来完成。Python变量trainingSet是一个整数列表,其中的值从0到49。接下来,随机选择其中10个文件 。选择出的数字所对应的文档被添加到测试集,同时也将其从训练集中剔除。

 垃圾邮件分类完整代码 

from numpy import *# 创建不重复词的列表 ———— 词汇表
def createVocabList(dataSet):vocabSet = set([])                       # 创建一个空集for document in dataSet:vocabSet = vocabSet | set(document)  # 创建两个集合的并集return list(vocabSet)                    # 返回不重复的词条列表# 输出文档向量
def setOfWords2Vec(vocabList, inputSet):returnVec = [0] * len(vocabList)             # 创建一个其中所含元素都为0的向量for word in inputSet:                        # 遍历文档中的所有单词if word in vocabList:                    # 如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1returnVec[vocabList.index(word)] = 1else:print("单词 %s 不在词汇表中!" % word)return returnVec# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):numTrainDocs = len(trainMatrix)                      # 获得训练的文档总数numWords = len(trainMatrix[0])                       # 获得每篇文档的词总数pAbusive = sum(trainCategory) / float(numTrainDocs)  # 计算文档是侮辱类的概率p0Num = ones(numWords)                               # 创建numpy.ones数组,初始化概率p1Num = ones(numWords)                               # 创建numpy.ones数组,初始化概率p0Denom = 2.0                                        # 初始化为2.0p1Denom = 2.0                                        # 初始化为2.0for i in range(numTrainDocs):if trainCategory[i] == 1:p1Num += trainMatrix[i]                      # 向量相加,统计侮辱类的条件概率的数据,即P(w0|1),P(w1|1),P(w2|1)···p1Denom += sum(trainMatrix[i])else:p0Num += trainMatrix[i]                      # 向量相加,统计非侮辱类的条件概率的数据,即P(w0|0),P(w1|0),P(w2|0)···p0Denom += sum(trainMatrix[i])p1Vect = log(p1Num / p1Denom)                        # 侮辱类,每个元素除以该类别中的总词数p0Vect = log(p0Num / p0Denom)                        # 非侮辱类,每个元素除以该类别中的总词数return p0Vect, p1Vect, pAbusive                      # 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 bagOfWords2VecMN(vocabList, inputSet):returnVec = [0] * len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1return returnVec# 文件解析
def textParse(bigString):  # 输入字符串, 输出单词列表import relistOfTokens = re.split(r'[\W*]', bigString)                    # 字符串切分,去掉除单词、数字外的任意字符串return [tok.lower() for tok in listOfTokens if len(tok) > 2]    # 除了单个字母外,其他字符串全部转换成小写# 完整的垃圾邮件测试函数
def spamTest():docList = []                 # 文档列表classList = []               # 文档标签fullText = []                # 全部文档内容集合for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个wordList = textParse(open('email/spam/%d.txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件wordList = textParse(open('email/ham/%d.txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 非垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,vocabList = createVocabList(docList)                             # 创建不重复的词汇表trainingSet = list(range(50))                                    # 为训练集添加索引testSet = []                                                     # 创建测试集for i in range(10):                                              # 目的为了从50个邮件中,随机挑选出40个作为训练集,10个做测试集randIndex = int(random.uniform(0, len(trainingSet)))         # 随机产生索引testSet.append(trainingSet[randIndex])                       # 添加测试集的索引值del (trainingSet[randIndex])                                 # 在训练集中,把加入测试集的索引删除trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量trainClasses = []                                                # 训练集类别标签for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表ttrainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数print('词表:\n', vocabList)print('p0V:\n', p0V)print('p1V:\n', p1V)print('pSpam:\n', pSpam)errorCount = 0                                                   # 用于计数错误分类for docIndex in testSet:                                         # 循环遍历训练集wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])  # 获得测试集的词集模型if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:errorCount += 1                                          # 预测值和真值不一致,则错误分类计数加1print("分类错误集", docList[docIndex])print('错误率: ', float(errorCount) / len(testSet))# return vocabList,fullText

实现邮件分类

# 邮件分类器
def classifyEmail():docList = []                 # 文档列表classList = []               # 文档标签fullText = []                # 全部文档内容集合for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个wordList = textParse(open('email/spam/%d.txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件wordList = textParse(open('email/ham/%d.txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表docList.append(wordList)                                     # 非垃圾邮件加入文档列表fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,vocabList = createVocabList(docList)                             # 创建不重复的词汇表trainingSet = list(range(50))                                    # 为训练集添加索引trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量trainClasses = []                                                # 训练集类别标签for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数testList = textParse(open('email/test/1.txt').read())            # 读取邮件,将大字符串并将其解析为字符串列表testVector = bagOfWords2VecMN(vocabList, testList)               # 获得测试集的词集模型if classifyNB(array(testVector), p0V, p1V, pSpam):result = "垃圾邮件"else:result = "正常邮件"print("输入邮件内容为: ")print(' '.join(testList))print('该邮件被分类为: ', result)
if __name__ == '__main__':classifyEmail()

 测试结果:

朴素贝叶斯实验总结

本次实验为实现垃圾邮件分类,从条件概率的格式推演到文本分类的基本实现,再到最终的垃圾邮件分类,做了一系列的工作。利用朴素贝叶斯来进行垃圾邮件分类的好处就是,朴素贝叶斯模型发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率,并且算法也比较简单,容易实现,对于小规模的数据效果很不错。

实验中遇到的两个问题,都是关于读取垃圾邮件txt文件的。第一个问题是运行输出的结果数据集为空,经过查找发现是读取问题,解决办法读取的方式改为r'[\W*]';把另外一个问题是txt文件的编码出错,于是把txt文件的编码改为了UTF-8,于是就可以了。

朴素贝叶斯的缺点:如果我们使用了样本属性真实情况其实并不是相互独立性的,那么其实这样的分类效果可能不会很好。而且需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候,会由于假设的先验模型的原因导致预测效果不佳。

朴素贝叶斯(垃圾邮件分类)相关推荐

  1. Python实现基于朴素贝叶斯的垃圾邮件分类 标签: python朴素贝叶斯垃圾邮件分类 2016-04-20 15:09 2750人阅读 评论(1) 收藏 举报 分类: 机器学习(19) 听说

    Python实现基于朴素贝叶斯的垃圾邮件分类 标签: python朴素贝叶斯垃圾邮件分类 2016-04-20 15:09 2750人阅读 评论(1) 收藏 举报  分类: 机器学习(19)  听说朴 ...

  2. python实现朴素贝叶斯垃圾邮件分类

    查看通俗易懂的贝叶斯垃圾邮件分类原理 请点击此处 下载邮件数据 请点击此处 import os import re import string import math import numpy as ...

  3. 朴素贝叶斯-垃圾邮件分类实现

    1. 前言 <朴素贝叶斯算法(Naive Bayes)>,介绍了朴素贝叶斯原理.本文介绍的是朴素贝叶斯的基础实现,用来垃圾邮件分类. 2. 朴素贝叶斯基础实现 朴素贝叶斯 (naive B ...

  4. 朴素贝叶斯-垃圾邮件(中文的)处理

    #coding=utf-8 from sklearn.naive_bayes import MultinomialNB,GaussianNB import numpy as np import jie ...

  5. 贝叶斯垃圾邮件分类问题中联合概率的推导

    主旨 讨论贝叶斯垃圾邮件分类问题中联合概率的计算问题.通过借鉴现有的资料,整理出一种数学上等价,同时基于本科概率论课程较容易理解的计算公式. 背景知识 2002年Paul Graham提出了一种利用贝 ...

  6. 朴素贝叶斯——垃圾邮件过滤

    文章目录 利用朴素贝叶斯进行文档分类 1.获取数据集 2.切分文本 3.构建词表和分类 4.构建分类器 5.测试算法 利用朴素贝叶斯进行垃圾邮件过滤 1.导入数据集 2.垃圾邮件预测 总结 利用朴素贝 ...

  7. 机器学习-朴素贝叶斯-垃圾邮件

    一:朴素贝叶斯算法概述 1:朴素贝叶斯(Naïve Bayes, NB)算法,是一种基于贝叶斯定理与特征条件独立假设的分类方法.朴素:特征条件独立:贝叶斯:基于贝叶斯定理.属于监督学习的生成模型,实现 ...

  8. 机器学习实战4(1):朴素贝叶斯:垃圾邮件的识别

    一.朴素贝叶斯基础知识 预备数学知识: A. 无约束条件的优化 1.求极值问题 人工智能中最核心的数学环节是求出一个目标函数(object function)的最小值/最大值.求出一个函数最小是/最大 ...

  9. 文本处理之贝叶斯垃圾邮件分类

    本文所讲解的是如何通过Python将文本读取,并且将每一个文本生成对应的词向量并返回. 文章的背景是将50封邮件(包含25封正常邮件,25封垃圾邮件)通过贝叶斯算法对其进行分类. 主要分为如下几个部分 ...

  10. 第四章 朴素贝叶斯-垃圾邮件过滤

    #朴素贝叶斯之垃圾邮件过滤 import os #----------------------1.获取数据集----------------------- import pandas as pd''' ...

最新文章

  1. 分布式系统关注点:弹性架构
  2. ThinkPhp框架基础知识
  3. python编程头文件_python头文件怎么写
  4. 【工具】克隆题库(适用于所有以POJ2005-2017为模板的OJ平台)
  5. Quartz 第六课 CronTrigger(官方文档翻译)
  6. 电脑显示服务器负载信息失败,线上服务mcelog负载异常分析处理流程
  7. Linux常用命令大全(三)
  8. 科大讯飞2019机械核心部件寿命预测,亚军方案
  9. 解决js动态改变dom元素属性后页面及时渲染问题
  10. 游戏本自动掉帧_机 · 科普帖丨如何在夏天告别游戏掉帧的问题
  11. 3,ActiveMQ-入门(基于JMS发布订阅模型)
  12. 重庆大学计算机学院考研,2021年重庆大学计算机学院考研指南
  13. 网络层(六)MAC地址与IP地址
  14. Word 紧贴表格之后添加新行
  15. php直接拨号代码,c#自动ADSL拨号代码
  16. rancher添加镜像库
  17. 网络流24题 最小路径覆盖(DCOJ8002)
  18. 01.电脑黑客基本知识
  19. 路由器局域网设置_教你如何修改路由器LAN口IP地址的方法
  20. Hexo - Next - Mist 风格主题的美化(二)

热门文章

  1. 工大科雅深交所上市:市值45亿 齐承英家族是大股东
  2. 匿名社交APP都是死于同一个问题,关系重大却注定无解?
  3. 错误模块名称: KERNELBASE.dll
  4. 从十几台电脑到百万IT投资 CIO张宝杰谈主动出击
  5. 生命力强悍的VB.net
  6. python开发项目流程_开发流程
  7. 特种设备全程数字化项目管理系统
  8. Debian10搭建bind9主服务器搭建
  9. C++ - 智能指针
  10. uniapp开发小程序引入折线图