【机器学习实战二:朴素贝叶斯算法之过滤垃圾邮件】
来源:互联网 发布:网络的利与弊议征文 编辑:程序博客网 时间:2024/05/06 11:01
http://blog.csdn.net/u013634684/article/details/49306563
分类:
版权声明:本文为博主原创文章,未经博主允许不得转载。
一、部分说明
----------------------------------------------------------------
1、本文代码是《机器学习实战》这本书的例程。点击下载《机器学习实战》及原书中的源代码;
2、运行环境为:window10+python3.2+各种python机器学习库。
安装可参考:点击打开链接
3、本文注重代码的实现过程,其基本知识请参考《机器学习实战》和一些知名博客。
4、本人属于初学者,有些注释部分可能不对,还请指正。
5、(1)、本代码从原来的python2.x改为python3.x;
(2)、加入详细的注释,方便理解;
(3)、还有加入自己想要实现的一些功能。
----------------------------------------------------------------
二、重点回顾
1、朴素贝叶斯算法原理:
2、朴素贝叶斯算法原理用于垃圾邮件过滤:
3、注意事项
(1)、为了防止步骤四的小数相乘造成精度损失(及比较小的数相乘最后会被当作0),故通过相乘比较大小转化为对数相加,避免此类问题的出现,影响实验结果;
(2)、分类时候还分为词集模式,知关心某个单词是否出现在邮件中;词袋模式,不仅关心单词是否出现还关心出现的次数;
(3)、其他一些具体的注意事项,会在代码中标注,可以查看,方便理解;
三、源代码
- <strong>'''''***********************************************************
- Copyright (C), 2015-2020, cyp Tech. Co., Ltd.
- FileName: 朴素贝叶斯实例.cpp
- Author: cyp
- Version : v1.0
- Date: 2015-10-21 上午10:38
- Description: 利用朴素贝叶斯原理对邮件进行分类
- Function List:
- 1. createVocalList:计算输入各集的并集,且每个元素是unique
- 2. setofWords2Vec: 运用词集方式将数据预处理
- 3. bagofWords2Vec: 运用词袋方式将数据预处理
- 4. trainNB0: 训练数据
- 5. classifyNB: 对email进行分类
- 6. test 相当于主函数,训练模型并测试
- ***********************************************************'''
- '''''***********************************************************
- 需要导入的模块
- ***********************************************************'''
- import random
- import math
- import numpy as np
- import os
- '''''***********************************************************
- Function: createVocalList
- Description: 计算输入各集的并集,且每个元素是unique
- Calls:
- Called By: test
- Input: dataSet输入的数据集,及单词向量集
- Return: 返回输入数据集的并集,返回数据的数据类型是list
- 表示出现过的单词
- ************************************************************'''
- def createVocalList(dataSet):
- vocalSet = set([]) #创建一个空集
- for data in dataSet:
- vocalSet = vocalSet | set(data) #利用set的特性求两个集合的并集
- return list(vocalSet) #以list的方式返回结果
- '''''***********************************************************
- Function: setofWords2Vec
- Description: 判断的向量的单词是否在词库中是否出现,如果出现
- 则标记为1,否则标记为0
- Calls:
- Called By: test
- Input:
- vocabList:
- 词库,曾经出现过的单词集合,即createVocalList
- inputSet:
- 测试的单词向量
- Return: returnVec是一个同vocalList同大小的数据,如果inputset单词
- 出现在vocalList则将returnVec对应的位置置1,否则为0
- ************************************************************'''
- def setofWords2Vec(vocalList,inputset):
- returnVec = [0]*len(vocalList)
- #同vocalList同大小的list,开始假设每个单词都没出现,即全为0
- for word in inputset:
- if word in vocalList: #如果输入的单词出现在词库中,则置1
- returnVec[vocalList.index(word)] = 1
- else: #如果没出现在词库中,默认为0,并输出
- print("the word:%s is not in my Vocabulary!"%word)
- return returnVec #返回结果
- '''''***********************************************************
- Function: bagofWords2Vec
- Description: 统计的单词是否在词库中出现频率
- Calls:
- Called By: test
- Input:
- vocabList:
- 词库,曾经出现过的单词集合,即createVocalList
- inputSet:
- 测试的单词向量
- Return: returnVec是一个同vocalList同大小的数据,对应位置
- 表示该单词出现的个数
- ************************************************************'''
- def bagofWords2Vec(vocalList,inputset):
- returnVec = [0]*len(vocalList)
- #同vocalList同大小的list,开始假设每个单词都没出现,即全为0
- for word in inputset:
- if word in vocalList: #如果输入的单词出现在词库中,则加1
- returnVec[vocalList.index(word)] += 1
- return returnVec #返回结果
- '''''***********************************************************
- Function: trainNB0
- Description: 统计侮辱性email出现概率,侮辱性邮件各单词出现的概率,非
- 侮辱性email各单词出现概率
- Calls:
- Called By: test
- Input:
- trainDataSet:参与训练的数据集,即setofWords2Vec返回数据的集合
- trainLabels:训练数据的标签
- Return:
- pShame:侮辱性email
- p0Vect:非侮辱性email中单词出现的概率
- p1Vect:侮辱性email中单词出现的概率
- ************************************************************'''
- def trainNB0(trainDataSet,trainLabels):
- numTrains = len(trainDataSet) #训练数据的组数
- numWords = len(trainDataSet[0]) #每组训练数据的大小
- pShame = sum(trainLabels)/float(numTrains)
- #标签中1表示侮辱,0表示非侮辱,故上述统计侮辱性email出现概率
- #zeros(numWords)表示1*numWords数组,非numWords*numWords数组
- #p0Num = np.zeros(numWords) #存储统计非侮辱性邮件各单词出现频率
- #p1Num = np.zeros(numWords) #存储统计侮辱性邮件各单词出现频率
- #p0SumWords = 0.0 #非侮辱性邮件中单词总数
- #p1SumWords = 0.0 #侮辱性邮件中单词总数
- #为了防止与0相乘,故初始化为1,因为两者的初始化一样,所以不影响结果
- p0Num = np.ones(numWords) #存储统计非侮辱性邮件各单词出现频率
- p1Num = np.ones(numWords) #存储统计侮辱性邮件各单词出现频率
- p0SumWords = 2.0 #非侮辱性邮件中单词总数
- p1SumWords = 2.0 #侮辱性邮件中单词总数
- for i in range(numTrains):
- if trainLabels[i]==1: #如果为侮辱性email
- p1Num += trainDataSet[i] #统计非侮辱性邮件各单词
- else:
- p0Num += trainDataSet[i] #统计侮辱性邮件各单词
- p0SumWords = sum(p0Num) #计算非侮辱性邮件中单词总数
- p1SumWords = sum(p1Num) #计算侮辱性邮件中单词总数
- p0Vect = p0Num/p0SumWords #非侮辱性邮件中单词出现的概率
- p1Vect = p1Num/p1SumWords #侮辱性邮件中单词出现的概率
- return pShame,p0Vect,p1Vect
- '''''***********************************************************
- Function: classifyNB
- Description: 对email进行分类
- Calls:
- Called By: test
- Input:
- vec2Classify:要分类的数据
- pShame:侮辱性email
- p0Vect:非侮辱性email中单词出现的概率
- p1Vect:侮辱性email中单词出现的概率
- Return:
- 分类的结果,1表示侮辱性email,0表示非侮辱性email
- ************************************************************'''
- def classifyNB(vec2Classify,p0Vect,p1Vect,pShame):
- #由于小数相乘,会有很大误差,故先求对数再相乘
- temp0 = vec2Classify*p0Vect
- temp1 = vec2Classify*p1Vect
- temp00 = []
- temp11 = []
- #分步求对数,因为log不能处理array,list
- for x in temp0:
- if x>0:
- temp00.append(math.log(x))
- else:
- temp00.append(0)
- for x in temp1:
- if x>0:
- temp11.append(math.log(x))
- else:
- temp11.append(0)
- p0 = sum(temp00)+math.log(1-pShame) #属于非侮辱性email概率
- p1 = sum(temp11)+math.log(pShame) #属于侮辱性email概率
- if p1 > p0: #属于侮辱性email概率大于属于非侮辱性email概率
- return 1
- else:
- return 0
- '''''***********************************************************
- Function: text2VecOfWords
- Description: 从email的string中提取单词
- Calls:
- Called By: test
- Input:
- string: email字符串
- Return:
- 单词向量
- ************************************************************'''
- def text2VecOfWords(string):
- import re #正则表达式工具
- listOfWolds = re.split(r"\W*",string)
- #分割数据,其分隔符是除单词,数字外任意的字符串
- return [word.lower() for word in listOfWolds if len(word)>2]
- #单词不区分大小写,及全部转换为(小写),滤除没用短字符串
- '''''***********************************************************
- Function: test
- Description: 将数据部分用来训练模型,部分用来测试
- Calls: text2VecOfWords
- createVocalList
- trainNB0
- classifyNB
- Called By: main
- Input:
- Return:
- ************************************************************'''
- def test():
- emailList = [] #存放每个邮件的单词向量
- emailLabel = [] #存放邮件对应的标签
- cwd = "C:\\Users\\cyp\\Documents\\sourcecode\\machinelearning\\my__code\\chapter4\\"
- for i in range(1,26):
- #读取非侮辱邮件,并生成单词向量
- wordList = text2VecOfWords(open(cwd+r"email\ham\%d.txt"%i,encoding='Shift_JIS').read())
- emailList.append(wordList)#将单词向量存放到emailList中
- emailLabel.append(0) #存放对应的标签
- wordList = text2VecOfWords(open(cwd+r"email\spam\%d.txt"%i,encoding='Shift_JIS').read())
- #读取侮辱邮件,并生成单词向量
- emailList.append(wordList)#将单词向量存放到emailList中
- emailLabel.append(1) #存放对应的标签
- vocabList = createVocalList(emailList)#由所有的单词向量生成词库
- trainSet = [i for i in range(50)] #产生0-49的50个数字
- testIndex = [] #存放测试数据的下标
- for i in range(10): #从[0-49]中随机选取10个数
- randIndex = int(random.uniform(0,len(trainSet)))
- #随机生成一个trainSet的下标
- testIndex.append(trainSet[randIndex])#提取对应的数据作为训练数据
- del(trainSet[randIndex]) #删除trainSet对应的值,以免下次再选中
- trainDataSet = [] #存放训练数据(用于词集方法)
- trainLabels = [] #存放训练数据标签(用于词集方法)
- trainDataSet1 = [] #存放训练数据(用于词袋方法)
- trainLabels1 = [] #存放训练数据标签(用于词袋方法)
- for index in trainSet: #trainSet剩余值为训练数据的下标
- trainDataSet.append(setofWords2Vec(vocabList,emailList[index]))
- #提取训练数据
- trainLabels.append(emailLabel[index])
- #提取训练数据标签
- trainDataSet1.append(bagofWords2Vec(vocabList,emailList[index]))
- #提取训练数据
- trainLabels1.append(emailLabel[index])
- #提取训练数据标签
- pShame,p0Vect,p1Vect = trainNB0(trainDataSet,trainLabels)#开始训练
- pShame1,p0Vect1,p1Vect1 = trainNB0(trainDataSet1,trainLabels1)#开始训练
- errorCount = 0.0 #统计测试时分类错误的数据的个数
- errorCount1= 0.0 #统计测试时分类错误的数据的个数
- for index in testIndex:
- worldVec = setofWords2Vec(vocabList,emailList[index])#数据预处理
- #进行分类,如果分类不正确,错误个位数加1
- if classifyNB(worldVec,p0Vect,p1Vect,pShame) != emailLabel[index]:
- errorCount += 1
- worldVec = bagofWords2Vec(vocabList,emailList[index])#数据预处理
- #进行分类,如果分类不正确,错误个位数加1
- if classifyNB(worldVec,p0Vect1,p1Vect1,pShame1) != emailLabel[index]:
- errorCount1 += 1
- #输出分类错误率
- print("As to set,the error rate is :",float(errorCount)/len(testIndex))
- print("AS to bag,the error rate is :",float(errorCount1)/len(testIndex))
- '''''***********************************************************
- Function: main
- Description: 运行test函数
- Calls: test
- Called By:
- Input:
- Return:
- ************************************************************'''
- if __name__=="__main__":
- test()</strong>
- <span style="font-family: Microsoft YaHei; font-size: 18px;"><strong>四、结果展示</strong></span>
0 0
- 【机器学习实战二:朴素贝叶斯算法之过滤垃圾邮件】
- 【机器学习实战二:朴素贝叶斯算法之过滤垃圾邮件】
- [机器学习实战]--朴素贝叶斯过滤垃圾邮件
- 【读书笔记】机器学习实战-4.6节 朴素贝叶斯过滤垃圾邮件
- 『机器学习实战』使用朴素贝叶斯过滤垃圾邮件
- Python3:《机器学习实战》之朴素贝叶斯(3)过滤垃圾邮件
- 《机器学习实战》学习笔记:基于朴素贝叶斯的垃圾邮件过滤
- 机器学习之实战朴素贝叶斯算法
- 机器学习之实战朴素贝叶斯算法
- 机器学习之实战朴素贝叶斯算法
- 机器学习之实战朴素贝叶斯算法
- 机器学习第五课----朴素贝叶斯应用于垃圾邮件过滤
- [机器学习]贝叶斯垃圾邮件过滤算法
- 《机器学习实战》学习笔记(三)之朴素贝叶斯(下)过滤垃圾邮件、获取区域倾向、新浪新闻分类 (sklearn)
- 机器学习实战-使用朴素贝叶斯分类器来做垃圾邮件分类
- 机器学习Matlab实战之垃圾邮件分类————朴素贝叶斯模型
- 机器学习实例一:利用朴素贝叶斯算法识别垃圾邮件
- <机器学习实战>--朴素贝叶斯实战(二)
- 配置Tomcat 输入ip可以直接访问项目的方法
- 【杭电oj】1432 - Lining Up(数论)
- SQL多表连接查询(详细实例)
- I/O重定向:改变了数据的输出或输入来源
- C语言中的位操作
- 【机器学习实战二:朴素贝叶斯算法之过滤垃圾邮件】
- JSPatch-使用经验记录
- Java异常处理-原则
- StarUML使用说明-指导手册
- Eclipse异常关闭后启动闪退
- [LeetCode]328. Odd Even Linked List
- 微信退款和支付宝退款接口调用(java版)
- 数据库的几种连接查询
- Unity编辑器扩展-菜单项