《机器学习实战》— 基于概率论的分类方法:朴素贝叶斯

一、朴素贝叶斯算法中相关概念介绍

1、朴素贝叶斯算法优缺点

优点:可以处理多类别问题,在数据较少的情况下依然有效

缺点:对输入数据的准备方式较敏感

2、适用类型:标称型函数

3、基于贝叶斯决策的分类方法

如果p1(x,y) > p2(x,y),则(x,y)为红色一类,类别为1。

如果p1(x,y) 

3、什么是条件概率?

推导:

         

 

 

由  

故  

4、使用条件概率进行分类

如果p(c1 | x,y)> p(c2 | x,y),那么属于类别c1

如果p(c1 | x,y)< p(c2 | x,y),那么属于类别c2

5、算法分析

:表示这个词在分类中的概率

:表示类别在整体中的概率

:表示这个词在整体中出现的概率

二、代码实现

1、创建实验样本

#创建一些实验样本
def loadDataSet():
    postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                 ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                 ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    classVec = [0,1,0,1,0,1]  #1代表侮辱性文字,0代表正常言论
    return postingList,classVec

2、创建一个包含在所有文档中出现的不重复词的列表

#创建一个包含在所有文档中出现的不重复词的列表
def createVocabList(dataSet):
    vocabSet=set([])  #创建一个空集
    #将每篇文档返回的新词集合添加到该集合
    for document in dataSet:
        vocabSet=vocabSet|set(document)#用于求两个集合的并集
    return list(vocabSet)

3、比较词汇表和输入文档,看输入文档中的字符哪些在词汇表中出现过

输出的是向量文档,向量的每个元素为1或0,分别表示词汇表中的单词在输入文档中是否出现

#比较词汇表和输入文档,看输入文档中的字符哪些在词汇表中出现过
#vocabList:词汇表
#inputSet:某个文档
#文档词集模型:每个词只能出现一次
def setOfWords2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList) #创建一个和词汇表等长的向量,将其元素都设置为0
    for word in inputSet:#遍历文档中所有单词,如果出现词汇表中的单词,则将输出文档向量中对应的值设置为1
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    #输出的是向量文档,向量的每个元素为1或0,分别表示词汇表中的单词在输入文档中是否出现
    return returnVec

#词袋模型:每个词可出现多次
def bagOfwrods2VecMN(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

4、测试

import bayes
from numpy import *
import feedparser
#创建一些实验样本
listOPosts,listClasses=bayes.loadDataSet()
#创建一个包含在所有文档中出现的不重复词的列表
myVocabList=bayes.createVocabList(listOPosts)
print(myVocabList)
#比较词汇表和输入文档,看输入文档中的字符哪些在词汇表中出现过
returnVec=bayes.setOfWords2Vec(myVocabList,listOPosts[0])
print(returnVec)

5、朴素贝叶斯分类器训练函数

#朴素贝叶斯分类器训练函数
#计算文档中的各个单词在各个分类中出现的概率(在0分类和1分类中出现的概率分别是多少)
#trainMatrix:文档矩阵
#trainCategory:每篇文档类别标签所构成的向量
#注意:这是一个两分类问题,计算p(1),则可由1-p(1)得到p(0),对于多于两分类问题,则需要对代码稍加修改
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs=len(trainMatrix) #6:表示一共有6个元素项
    numWords=len(trainMatrix[0])  #32:表示第一个元素项有32个字符
   #trainCategory:[0, 1, 0, 1, 0, 1]
    pAbusive=sum(trainCategory)/float(numTrainDocs)  #计算类别为侮辱性文字1类别出现的概率
    p0Num = ones(numWords)#32个元素的1向量
    p1Num = ones(numWords)
    p0Denom=2.0
    p1Denom=2.0
    for i in range(numTrainDocs):
        #一旦某个词在某一文档出现,则该词对应的个数就加1,
        if trainCategory[i] == 1:#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

6、朴素贝叶斯分类函数

#朴素贝叶斯分类函数
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

7、测试

for postinDoc in listOPosts:
    trainMat.append(bayes.setOfWords2Vec(myVocabList,postinDoc))
pv0,pv1,pAb=bayes.trainNB0(trainMat,listClasses)
print(pv0)
print(pv1)
print(pAb)
#测试分类函数
testEntry = [ 'my', 'dog','is','cute']
thisDoc = array(bayes.setOfWords2Vec(myVocabList, testEntry))
print(testEntry, 'classified as:', bayes.classifyNB(thisDoc, pv0, pv1, pAb))

《机器学习实战》— 基于概率论的分类方法:朴素贝叶斯_第1张图片

8、封装测试函数

def testingNB():
    listOPosts, listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    pv0, pv1, pAb = trainNB0(trainMat, listClasses)
    testEntry=['love','my','dalmation']
    thisDoc=array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as:',classifyNB(thisDoc,pv0,pv1,pAb))
    testEntry=['stupid','garbage']
    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
    print(testEntry, 'classified as:', classifyNB(thisDoc, pv0, pv1, pAb))
#封装测试函数
bayes.testingNB()

三、应用:垃圾邮件分类案例

《机器学习实战》— 基于概率论的分类方法:朴素贝叶斯_第2张图片

1、接收一个大字符串并将其解析为字符串列表

#接收一个大字符串并将其解析为字符串列表
def textParse(bigString):
  import re
  listOfTokens = re.split(r'\\W*',bigString)
  #去掉少于两个字符的字符串,并将所有字符串转化为小写
  return [tok.lower() for tok in listOfTokens if len(tok) > 2]

2、文件解析及完整的垃圾邮件测试函数

#文件解析及完整的垃圾邮件测试函数
def spamTest():
    docList=[]
    classList=[]
    fullText=[]
    #导入spam和ham下的文本文件,并将它们解析为词列表
    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=list(range(50))  #共50封邮件,表示从0-49的整数列表
    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(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 ('this error rate is : ' ,float(errorCount)/len(testSet))

调用此函数结果:

你可能感兴趣的:(机器学习实战,机器学习,朴素贝叶斯,基于概率论的分类方法)