使用贝叶斯过滤垃圾邮件
1.准备数据:切分文本
将字符串切分为词列表时,倘若没有split参数,则标点符号也会被当成词的一部分,可以使用正则表达式来切分句子,其中分隔符是除了单词,数字之外的任意字符串。
>>>import re
>>> regEx = re.compile('\\W*')
>>>listOfTokens = regEx.split(mySent)
>>>[tok.lower() for tok in listOftokens if len(tok)>0]
在实际的解析过程中,比如要用更高级的过滤器对HTML和URL对象进行处理
2.测试算法:使用朴素贝叶斯进行交叉验证
使用本地的数据,将邮件内容存放在txt文件中,只对邮件的第一行进行验证。spam和ham的文件夹下分别存储了两类邮件。
#本地文件解析以及完整的垃圾邮件测试函数
def textParse(bigString):
import re
#利用正则表达式去除标点,防止其作为分割符
listOfTokens = re.split(r"\W*",bigString)
#长度>2且全部转为小写
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())
#append方法是将参数整体作为元素进行添加
#extend方法是将参数拆解作为元素添加,可能有重复元素
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)
vocablList = createVocabList(docList)
trainingSet = [i for i in range(50)]
testSet = []
#随机挑取10个随机数作为要测试的样本索引
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(setOfWord2Vec(vocablList,docList[docIndex]))
trainClasses.append(classList[docIndex])
#训练得到各个词对应的概率权重大小
p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
errorCount = 0
for docIndex in testSet:
wordVector = setOfWord2Vec(vocablList,docList[docIndex])
#将预测值与实际值进行比较
if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
errorCount += 1
print('the error rate is :',float(errorCount)/len(testSet))
textParse()函数接受一个大写字符串并将其解析为单词列表spamTest()对贝叶斯垃圾邮件分类器进行自动化处理,首先构建一个测试集和训练集,总共50个邮件,然后得到所有词的词典,随机选取10个样本作为测试集,剩余的用作训练集。利用词典构建各个样本的词向量,并将其添加到训练矩阵中,通过训练矩阵和标签列表,得到各个词对应的概率权重列表。最后得到测试集的预测值,进而求得错误率。