朴素贝叶斯(垃圾邮件分类)
一.基于贝叶斯决策理论的分类方法
朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法。对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同。比如决策树,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,于是就可以了。
朴素贝叶斯的缺点:如果我们使用了样本属性真实情况其实并不是相互独立性的,那么其实这样的分类效果可能不会很好。而且需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候,会由于假设的先验模型的原因导致预测效果不佳。
朴素贝叶斯(垃圾邮件分类)相关推荐
- Python实现基于朴素贝叶斯的垃圾邮件分类 标签: python朴素贝叶斯垃圾邮件分类 2016-04-20 15:09 2750人阅读 评论(1) 收藏 举报 分类: 机器学习(19) 听说
Python实现基于朴素贝叶斯的垃圾邮件分类 标签: python朴素贝叶斯垃圾邮件分类 2016-04-20 15:09 2750人阅读 评论(1) 收藏 举报 分类: 机器学习(19) 听说朴 ...
- python实现朴素贝叶斯垃圾邮件分类
查看通俗易懂的贝叶斯垃圾邮件分类原理 请点击此处 下载邮件数据 请点击此处 import os import re import string import math import numpy as ...
- 朴素贝叶斯-垃圾邮件分类实现
1. 前言 <朴素贝叶斯算法(Naive Bayes)>,介绍了朴素贝叶斯原理.本文介绍的是朴素贝叶斯的基础实现,用来垃圾邮件分类. 2. 朴素贝叶斯基础实现 朴素贝叶斯 (naive B ...
- 朴素贝叶斯-垃圾邮件(中文的)处理
#coding=utf-8 from sklearn.naive_bayes import MultinomialNB,GaussianNB import numpy as np import jie ...
- 贝叶斯垃圾邮件分类问题中联合概率的推导
主旨 讨论贝叶斯垃圾邮件分类问题中联合概率的计算问题.通过借鉴现有的资料,整理出一种数学上等价,同时基于本科概率论课程较容易理解的计算公式. 背景知识 2002年Paul Graham提出了一种利用贝 ...
- 朴素贝叶斯——垃圾邮件过滤
文章目录 利用朴素贝叶斯进行文档分类 1.获取数据集 2.切分文本 3.构建词表和分类 4.构建分类器 5.测试算法 利用朴素贝叶斯进行垃圾邮件过滤 1.导入数据集 2.垃圾邮件预测 总结 利用朴素贝 ...
- 机器学习-朴素贝叶斯-垃圾邮件
一:朴素贝叶斯算法概述 1:朴素贝叶斯(Naïve Bayes, NB)算法,是一种基于贝叶斯定理与特征条件独立假设的分类方法.朴素:特征条件独立:贝叶斯:基于贝叶斯定理.属于监督学习的生成模型,实现 ...
- 机器学习实战4(1):朴素贝叶斯:垃圾邮件的识别
一.朴素贝叶斯基础知识 预备数学知识: A. 无约束条件的优化 1.求极值问题 人工智能中最核心的数学环节是求出一个目标函数(object function)的最小值/最大值.求出一个函数最小是/最大 ...
- 文本处理之贝叶斯垃圾邮件分类
本文所讲解的是如何通过Python将文本读取,并且将每一个文本生成对应的词向量并返回. 文章的背景是将50封邮件(包含25封正常邮件,25封垃圾邮件)通过贝叶斯算法对其进行分类. 主要分为如下几个部分 ...
- 第四章 朴素贝叶斯-垃圾邮件过滤
#朴素贝叶斯之垃圾邮件过滤 import os #----------------------1.获取数据集----------------------- import pandas as pd''' ...
最新文章
- 分布式系统关注点:弹性架构
- ThinkPhp框架基础知识
- python编程头文件_python头文件怎么写
- 【工具】克隆题库(适用于所有以POJ2005-2017为模板的OJ平台)
- Quartz 第六课 CronTrigger(官方文档翻译)
- 电脑显示服务器负载信息失败,线上服务mcelog负载异常分析处理流程
- Linux常用命令大全(三)
- 科大讯飞2019机械核心部件寿命预测,亚军方案
- 解决js动态改变dom元素属性后页面及时渲染问题
- 游戏本自动掉帧_机 · 科普帖丨如何在夏天告别游戏掉帧的问题
- 3,ActiveMQ-入门(基于JMS发布订阅模型)
- 重庆大学计算机学院考研,2021年重庆大学计算机学院考研指南
- 网络层(六)MAC地址与IP地址
- Word 紧贴表格之后添加新行
- php直接拨号代码,c#自动ADSL拨号代码
- rancher添加镜像库
- 网络流24题 最小路径覆盖(DCOJ8002)
- 01.电脑黑客基本知识
- 路由器局域网设置_教你如何修改路由器LAN口IP地址的方法
- Hexo - Next - Mist 风格主题的美化(二)