4.6 示例:使用朴素贝叶斯过滤垃圾邮件
使用朴素贝叶斯解决一些现实生活中的问题时,需要从文本内容-->字符串列表-->词向量。
下面,将了解朴素贝叶斯一个最著名的应用:电子邮件垃圾过滤。
4.6.1 准备数据:切分文本
对于一个文本字符串,可以使用Python的string.split()方法切分。
虽然切分效果不错,但标点符号也被当成词的一部分。可以使用正则表达式来切分,其中分隔符是除单词、数字外的任意字符串。
现在得到词表,但是里面的空字符串需要去掉。可以计算每个字符串的长度,只返回长度大于0的字符串。
句子中的第一个单词是大写。如果目的是句子查找,那么这个特点会很有用。但这里文本只看成词袋,所以我们希望所有词的形式是一致的,不论它们是出现在句子中间
、结尾还是开头。使用Python中.lower()和.upper()转换成小写和大写。
4.6.2 测试算法:使用朴素贝叶斯进行交叉验证cross validation
将下面代码添加到bayes.py中:
#文件解析及完整的垃圾邮件测试函数 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):#导入文件夹spam和ham下的文件文本,并将其解析为词列表 wordList = textParse(open('email/spam/%d.txt' % i).read()) docList.append(wordList)#append表示追加 fullText.extend(wordList)#extend表示扩展 classList.append(1)#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)#训练集:整数列表,值从0-49 testSet = []#测试集 for i in range(10):#抽取测试集,随机构建训练集 randIndex = int(random.uniform(0, len(trainingSet)))#随机选取10个文件做训练集 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 = trainNB0(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)
注:spamTest():本例中共50封电子邮件,其中10封被随机抽取为测试集,40封为训练集。
这种随机选取数据的一部分作为训练集,剩余作为测试集的过程叫做留存交叉验证(hold-out cross validation).
假定现在只完成一次迭代,那么为了更精确地估计分类器的错误率,就应该进行多次迭代后求出平均错误率。
这里是随机抽取,所以每次结果可能有所差别。