4 基于概率论的分类方法:朴素贝叶斯(二)

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).

假定现在只完成一次迭代,那么为了更精确地估计分类器的错误率,就应该进行多次迭代后求出平均错误率。

这里是随机抽取,所以每次结果可能有所差别。

 

posted @ 2016-01-30 17:53  hudongni1  阅读(594)  评论(0编辑  收藏  举报