【机器学习实战】03-朴素贝叶斯算法实例

【博客的主要内容主要是自己的学习笔记,并结合个人的理解,供各位在学习过程中参考,若有疑问,欢迎提出;若有侵权,请告知博主删除,原创文章转载还请注明出处。】

[机器学习实战:文本过滤器]

实例一:在线社区留言板过滤器

1 需求描述:

为维护在线社区留言板的正常次序,需屏蔽侮辱性的言论,需构建一个快速过滤器,如果某条留言使用了负面或侮辱性的言语,那么就将该留言标识为内容不当。

2 算法分析:【自问的过程】

1、拥有数据样本情况?

有若干条数据样本,其中每条“言论”均标识所属类别(即侮辱性言语或非侮辱性言语)

2、程序如何判断言语为侮辱性和非侮辱性?

  1. 朴素贝叶斯

将使用朴素贝叶斯公式:

Paste_Image.png

c 表示分类类别即:侮辱性言语和非侮辱性言语

对每个类别分母都一样,即需计算$P(w|c_i)$ 和 $P(c_i)$,在朴素贝叶斯中假设事件是相互独立的,故:
$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...P(w_n|c_i)$

  1. 需要计算什么?
    $P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$
    以上用文字描述:计算每个类别下各个单词出现的概率。由此,需要统计内容:
    a)每条言论下各个单词出现的次数;
    b)每个类别的单词总数;

  2. 数据分析:现有数据什么样?需要对数据如何处理?

  • a、对每条言语转换成向量数组;

  • b、制定“词典集合”,将每条言语做并集,去除重复单词;并将“词典集合”转换为向量数组;

  1. 特殊情况分析:
  • a、由于$P(w|c_i)=P(w_0|c_i)P(w_1|c_i)...*P(w_n|c_i)$ 是做乘法运算,若其中一个单词概率为0,则该言语概率为0。

    • [解决方法]将所有词出现数初始化为1,分母初始化为2。
  • b、太多很小数相乘,结果将趋近为0.

    • [解决方法]对乘积取自然对数。在代数中有ln(a*b) = ln(a) + ln(b)。

3 算法实现

#1、将文本转换为数字向量
##a、建立不重复的词汇表
def createVocabList(dataSet):
    vocabSet = set([])
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)
    

#test
myVocabLists = createVocabList(postingLists)   
    
##b、将每条言语转换为数字向量:建立与词汇表同等大小的言语向量,若言语中的词汇在词汇表中出现则标记为1,否则为0.
#vocabList:单词字典集合
#inputSet:单条文本
def setOfWords2Vec(vocabList,inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print "the word :%s is not in my vocabulary!" % word
    return returnVec

#test
wordsVec=[]
for postingList in postingLists:
    wordsVec.append(setOfWords2Vec(myVocabLists,postingList))

#trainMainx - 输入文档矩阵
#trainCategory - 由每篇文档类别标签所构成的向量
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    
    #初始化概率
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    
    p0Denom = 2.0
    p1Denom = 2.0
    
    #向量相加
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
            
    p1Vect = log(p1Num / p1Denom)
    p0Vect = log(p0Num / p0Denom)  
    
    return p0Vect,p1Vect,pAbusive
    
##test
p0Vect,p1Vect,pAbusive=trainNB0(wordsVec,classLists)

2 实例二:电子邮件垃圾过滤

如何从文本文档中构建自己的词列表
随机选择数据的一部分作为训练集,剩余部分作为测试集的过程称为“留存交叉验证”(hold-out cross validation)

思路:
1)构建词列表:对文本文档进行按词切分
2)交叉验证:对现有数据划分为训练集和测试集
3)朴素贝叶斯算法计算独立事件概率

  1. 计算算法准确率
    5)多次重复实验,提高正确率

textParse()接受一个大字符串并将其解析为字符串列表;
spamTest()对垃圾邮件分类器进行自动处理。主要:
1)解析文本文件编制成词列表;
2)构建测试集合训练集

######电子邮件垃圾过滤######
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(workList)
        fullText.extend(workList) 
        
        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=[]
    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(bagOfWord2VecMN(vocabList,docList[docIndex]))
        trainClasses.append(classList[docIndex])
        
        p0V,p1V,pSpam=trainNB(array(trainMat),array(trainClasses))      
        
    #统计错误率
    errorCount = 0 
    for docIndex in testSet:
        wordVector = bagOfWord2VecMN(vocabList,docList[docIndex])
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount +=1
            print "classification error:",docList[docIndex]
            print "the error rate is:", float(errorCount)/len(testSet)

3 实例三:使用朴素贝叶斯分类器从个人广告中获取区域倾向

对两个城市所发布的征婚广告信息,来比较这两个城市的人们在广告用词上是否不同。
如果结论是不同,那么他们各自常用的词是那些?
从人们的用词中,能否对不同城市的人所关心的内容有所了解?

该实例目的:通过观察单词和条件概率值来发现与特定城市相关的内容

calcMostFreq() 遍历词汇表中每个词并统计它在文本中出现的次数,然后根据出现次数从高到低对词典进行排序,最后返回排序最高的100个单词。

localWords() 主要:1)解析文本词列表;2)构建测试集合训练集
getTopWords() 训练并测试朴素贝叶斯分类器,返回使用的概率值。

你可能感兴趣的:(【机器学习实战】03-朴素贝叶斯算法实例)