摘要:这里用的是词袋模型,即一个词在文档中出现不止一次,每个单词可以出现多次。

1、准备数据:切分文本

前一节过滤网站恶意留言中词向量是给定的,下面介绍如何从文本文档中构建自己的词列表

先举例说明,在python提示符下输入:

>>> mySent='This book is the best book on python or M.L. I have ever laid eyes upon.'
>>> mySent.split()
['This', 'book', 'is', 'the', 'best', 'book', 'on', 'python', 'or', 'M.L.', 'I', 'have', 'ever', 'laid', 'eyes', 'upon.']
#标点符号也被当成了词的一部分,可以使用正则表达式来切分句子,其中分隔符是除单词、数字外的任意字符串
>>> import re
>>> regEx=re.compile('\\W*')
>>> listOfTokens=regEx.split(mySent)
>>> listOfTokens
['This', 'book', 'is', 'the', 'best', 'book', 'on', 'python', 'or', 'M', 'L', 'I', 'have', 'ever', 'laid', 'eyes', 'upon', '']
#去掉空字符串,通过计算每个字符串的长度,只返回长度大于0的字符串
>>> [tok for tok in listOfTokens if len(tok)>0]
['This', 'book', 'is', 'the', 'best', 'book', 'on', 'python', 'or', 'M', 'L', 'I', 'have', 'ever', 'laid', 'eyes', 'upon']
#将字符串全部转换成小写(.lower())或者大写(.upper())
>>> [tok.lower() for tok in listOfTokens if len(tok)>0]
['this', 'book', 'is', 'the', 'best', 'book', 'on', 'python', 'or', 'm', 'l', 'i', 'have', 'ever', 'laid', 'eyes', 'upon']

本例中共有50封电子邮件,采用的是email文件夹下的ham文件和spam文件,其中ham文件下有25份d.txt(d是1到25)文件,spam文件下也有25份d.txt(d是1到25)文件。其中的10封邮件被随机选择为测试集。以下分别是ham文件下1.txt的内容,spam文件下1.txt的内容:

 

创建一个bayes.py文件,添加以下代码:

#!/usr/bin/python
#-*- coding:utf-8 -*-
#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)
for word in inputSet:
if word in inputSet:
returnVec[vocabList.index(word)]+=1  #这里是词袋模型,与词集模型不一样
else:print "the word:%s is not in my Vocabulary!" % word
return returnVec
 

2、训练算法:从词向量计算概率

前面介绍了如何将一组单词转换为一组数字,接下来看看如何使用这些数字计算概率。现在已经知道一个词是否出现在一篇文档中,也知道该文档所属类别。

(1)

首先通过类别i中文档数除以总的文档数来计算概率P(Ci),然后计算P(w|Ci),即P(w0|Ci)P(w1Ci)...P(wN|Ci)来计算上述概率。

#朴素贝叶斯分类器训练函数
def trainNBO(trainMatrix,trainCategory):
numTrainDocs=len(trainMatrix)
numWords=len(trainMatrix[0])
pAbusive=sum(trainCategory)/float(numTrainDocs)
p0Num=ones(numWords);p1Num=ones(numWords) #计算p(w0|1)p(w1|1),避免其中一个概率值为0,最后的乘积为0
p0Demo=2.0;p1Demo=2.0 #初始化概率
for i in range(numTrainDocs):
if trainCategory[i]==1:
p1Num+=trainMatrix[i]
p1Demo+=sum(trainMatrix[i])
else:
p0Num+=trainMatrix[i]
p0Demo+=sum(trainMatrix[i])
#p1Vect=p1Num/p1Demo
#p0Vect=p0Num/p0Demo
p1Vect=log(p1Num/p1Demo) #计算p(w0|1)p(w1|1)时,大部分因子都非常小,程序会下溢出或得不到正确答案(相乘许多很小数,最后四舍五入会得到0)
p0Vect=log(p0Num/p0Demo)
return p0Vect,p1Vect,pAbusive

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 1
else:
return 0
#文件解析及完整的垃圾邮件测试函数
def textParse(bigString):
import re
listOfTokens=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):
wordList=textParse(open('email/spam/%d.txt'% i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
wordList=textParse(open('email/ham/%d.txt'% i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList=createVocabList(docList)
trainingSet=range(50);testSet=[]  #trainingSet是一个整数列表,其中的值从0到49
for i in range(10):   #随机选择其中10个文件
randIndex=int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex]) #选择出的数字所对应的文档被添加到测试集
del(trainingSet[randIndex])   #同时被选中的数据将从训练集中踢除
trainMat=[];trainClasses=[]
for docIndex in trainingSet:
trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam=trainNBO(array(trainMat),array(trainClasses))
errorCount=0
for docIndex in testSet:
wordVector=setOfWords2Vec(vocabList,docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
errorCount+=1
print 'the error rate is:',float(errorCount)/len(testSet)

下面对上述过程进行尝试,在python提示符下输入:

>>> reload(bayes)
<module 'bayes' from 'bayes.py'>
>>> bayes.spamTest()
the error rate is: 0.1
>>> bayes.spamTest()
the error rate is: 0.0

函数spamTest()会输出在10封随机选择的电子邮件上的分类错误绿。既然这些电子邮件是随机选择的,所以每次的输出结果可能有些差别。

解释:

>>> docList=[];classList=[];fullText=[]
>>> for i in range(1,26):
... wordList=bayes.textParse(open('email/spam/%d.txt'%i).read())
... docList.append(wordList)
... fullText.extend(wordList)
... classList.append(1)
...
>>> wordList
['experience', 'with', 'biggerpenis', 'today', 'grow', 'inches', 'more', 'the', 'safest', 'most', 'effective', 'methods', 'of_penisen1argement', 'save', 'your', 'time', 'and', 'money', 'bettererections', 'with', 'effective', 'ma1eenhancement', 'products', 'ma1eenhancement', 'supplement', 'trusted', 'millions', 'buy', 'today']
>>> docList
[['codeine', '15mg', 'for',..., 'buy', 'today']]
>>> fullText
['codeine', '15mg', 'for', ...,'buy', 'today']
>>> classList
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> len(wordList)
29
>>> len(docList)
25
>>> len(fullText)
795
>>> len(classList)
25
>>> docList=[];classList=[];fullText=[]
>>> for i in range(1,26):
... wordList=bayes.textParse(open('email/ham/%d.txt'%i).read())
... docList.append(wordList)
... fullText.extend(wordList)
... classList.append(0)
...
>>> wordList
['that', 'cold', 'there', 'going', 'retirement', 'party', 'are', 'the', 'leaves', 'changing', 'color']
>>> docList
[['codeine', '15mg', ..., 'changing', 'color']]
>>> fullText
['codeine', '15mg', ..., 'changing', 'color']
>>> classList
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> len(wordList)
11
>>> len(docList)
25
>>> len(fullText)
967
>>> len(classList)
25
>>> docList=[];classList=[];fullText=[]
>>> for i in range(1,26):
... wordList=bayes.textParse(open('email/spam/%d.txt'%i).read())
... docList.append(wordList)
... fullText.extend(wordList)
... classList.append(1)
... wordList=bayes.textParse(open('email/ham/%d.txt'%i).read())
... docList.append(wordList)
... fullText.extend(wordList)
... classList.append(0)
...
>>> wordList
['that', 'cold', 'there', 'going', 'retirement', 'party', 'are', 'the', 'leaves', 'changing', 'color']
>>> docList
[['codeine', '15mg', ..., 'changing', 'color']]
>>> fullText
['codeine', '15mg', ..., 'changing', 'color']
>>> classList
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
>>> len(wordList)
11
>>> len(docList)
50
>>> len(fullText)
1762
>>> len(classList)
50
>>> vocabList=bayes.createVocabList(docList)
>>> vocabList
['all', 'code', ..., 'others', 'once']
>>> len(vocabList)
692
>>> trainingSet=range(50);testSet=[]
>>> for i in range(10):
... randIndex=int(random.uniform(0,len(trainingSet)))
... testSet.append(trainingSet[randIndex])
... del(trainingSet[randIndex])
...
>>> trainMat=[];trainClasses=[]
>>> for docIndex in trainingSet:
... trainMat.append(bayes.setOfWords2Vec(vocabList,docList[docIndex]))
... trainClasses.append(classList[docIndex])
...
>>> shape(trainMat)
(40, 692) #表示40行692列,即40篇训练文档,692个不重复的词汇
>>> p0V,p1V,pSpam=bayes.trainNBO(array(trainMat),array(trainClasses))
>>> len(p0V)
692
>>> len(p1V)
692

这里一直出现的错误是将垃圾邮件误判为正常邮件,相比之下,将垃圾邮件误判为正常邮件要比正常邮件归到垃圾邮件好。

【Machine Learning in Action --4】朴素贝叶斯电子邮件垃圾过滤的更多相关文章

  1. Machine Learning in Action(3) 朴素贝叶斯算法

    贝叶斯决策一直很有争议,今年是贝叶斯250周年,历经沉浮,今天它的应用又开始逐渐活跃,有兴趣的可以看看斯坦福Brad Efron大师对其的反思,两篇文章:“Bayes'Theorem in the 2 ...

  2. 《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜

    <Machine Learning in Action>-- 白话贝叶斯,"恰瓜群众"应该恰好瓜还是恰坏瓜 概率论,可以说是在机器学习当中扮演了一个非常重要的角色了.T ...

  3. machine learning for hacker记录(3) 贝叶斯分类器

    本章主要介绍了分类算法里面的一种最基本的分类器:朴素贝叶斯算法(NB),算法性能正如英文缩写的一样,很NB,尤其在垃圾邮件检测领域,关于贝叶斯的网上资料也很多,这里推荐那篇刘未鹏写的http://mi ...

  4. 《Machine Learning in Action》—— 浅谈线性回归的那些事

    <Machine Learning in Action>-- 浅谈线性回归的那些事 手撕机器学习算法系列文章已经肝了不少,自我感觉质量都挺不错的.目前已经更新了支持向量机SVM.决策树.K ...

  5. 《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事

    在手撕机器学习系列文章的上一篇,我们详细讲解了线性回归的问题,并且最后通过梯度下降算法拟合了一条直线,从而使得这条直线尽可能的切合数据样本集,已到达模型损失值最小的目的. 在本篇文章中,我们主要是手撕 ...

  6. NLP系列(4)_朴素贝叶斯实战与进阶

    作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/50629608 htt ...

  7. NLP系列(4)_朴素贝叶斯实战与进阶(转)

    http://blog.csdn.net/han_xiaoyang/article/details/50629608 作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:htt ...

  8. 机器学习Matlab打击垃圾邮件的分类————朴素贝叶斯模型

    该系列来自于我<人工智能>课程回顾总结,以及实验的一部分进行了总结学习机 垃圾分类是有监督的学习分类最经典的案例,本文首先回顾了概率论的基本知识.则以及朴素贝叶斯模型的思想.最后给出了垃圾 ...

  9. 什么是机器学习的分类算法?【K-近邻算法(KNN)、交叉验证、朴素贝叶斯算法、决策树、随机森林】

    1.K-近邻算法(KNN) 1.1 定义 (KNN,K-NearestNeighbor) 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类 ...

随机推荐

  1. ZendStudio9之SVN项目代码提示丢失解决

    前几天转移服务器,SVN 也重建了个,但用着重建的项目发现代码提示丢失了...好郁闷..搞了半天终于找到解决的方法了! 如果你还保留有以前的 SVN 项目本地完整备份,可以直接拷贝以下三个文件到新项目 ...

  2. XTU 1245 Hamiltonian Path

    $2016$长城信息杯中国大学生程序设计竞赛中南邀请赛$C$题 简单题. 注意题目中给出的数据范围:$1 \le ai < bi \le n$,说明这是一个有向无环图,并且哈密顿路一定是$1 \ ...

  3. IntelliJ IDEA “Finds duplicated code”提示如何关闭

    发现重复的代码这个提示真的很烦啊,我们怎么关闭他呢. 设置在这里: Settings -> Editor -> Inspections -> General -> Duplic ...

  4. 推荐几个在线PDF转化成Word网站

    不想安装专业的pdf转换成word软件,希望大家喜欢!昨天用的https://www.pdftoword.com/# 成功搞定! 1.Free-PDFtoWord 在线转换工具: 地址:http:// ...

  5. 关于数据汇总方面返回Json数据的小小心得

    在一开始的开发中,计算好相关数据,然后通过 1.拼串 2.实例化Dictory对象再通过JavaScriptSerializer转换为json. 其中,2只适合于二维数据.1适合多维数据,但拼串比较费 ...

  6. 2.MyBatis有代理增删改

    2.1 创建一个javaweb项目MyBatis_Part1,并创建如下sql脚本 create user holly identified by sys; grant dba to holly; c ...

  7. 将LibreOffice文档批量转成PDF格式

    使用如下命令可以将文档一次性批量导出为pdf格式: -name -I /program/soffice.exe --headless --convert-to pdf '{}' find命令的-max ...

  8. Conversion to Dalvik format failed with error 1(android)

    1.如果不修改android sdk版本,则使用project clean 命令作用于某工程即可. (该处理方式只是在高版本中兼容了低版本工程,未真正意义上的升级) 2.如果修改android sdk ...

  9. informix数据迁移工具使用介绍

    一.dbschema  USAGE:     dbschema [-q] [-t tabname] [-s user] [-p user] [-r rolename] [-f procname]    ...

  10. python 基础学习4-with语句

    why use With? 有些事情需要事先进行设置,事后进行处理,with语句提供了一个很好的处理方式,例如文件读写处理,有时候可能忘记关闭文件,with可以很好地处理这种现象. with语句用来简 ...