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

4.1 基于贝叶斯决策理论的分类方法

  优点:在数据较少的情况下仍然有效,可以处理多类别问题。
  缺点:对于输入数据的准备方式较为敏感。
  适用数据类型:标称型数据。

贝叶斯决策理论
  朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论。
  贝叶斯决策理论的核心思想,即选择具有最高概率的决策。
       如果p1>p2(1,2为两个类别),那么类别为1.

4.2 条件概率

  条件概率==p(a|b)==表示在事件b发生的条件下a发生的概率。
                       p(a|b)=p(ab)/p(b)
                   而 p(ab)=p(b|a)p(a)

4.3 使用条件概率来分类

   分类准则:
            比较P(c1|x, y) 与 P(c2|x, y) 的大小,认为结果属于概率大的类别。P(c1|x, y)表示给定某个由x、y表示的数据点,那么该数据点来自类别c1的概率。
在这里插入图片描述

4.4 使用朴素贝叶斯进行文档分类

                            朴素贝叶斯是贝叶斯分类器的一个扩展,是用于文档分类的常用算法。
两个假设:(1)朴素:特征之间相互独立
                  (2)每个特征同等重要

                    朴素贝叶斯分类器通常有两种实现方式:一种基于贝努利模型实现,一种基于多项式模型实现。这里采用前一种实现方式。该实现方式中并不考虑词在文档中出现的次数只考虑出不出现,因此在这个意义上相当于假设词是等权重的。

4.5 使用 Python 进行文本分类

4.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','grabage'],
                 ['mr','licks','ate','my','steak','how',\
                  'to','stop','him'],
                 ['quit','buying','worthless','dog','food','stupid']]
    classVec=[0,1,0,1,0,1] #1代表侮辱性文字(stupid)
    return postingList,classVec

#创建包含文档中所有单词(不重复)列表
def createVocabList(dataSet):
    vocabSet=set([])        #创造一个空集合
    for document in dataSet:
        vocabSet=vocabSet | set(document) #集合并运算
    return list(vocabSet) 

#把单词列表转换为文档向量
def setOfWorld2Vec(vocabList,inputSet):
    returnVec=[0]*len(vocabList) #创建对应的向量
    for word in inputSet:  # word 为目标单词
        if word in vocabList:
            returnVec[vocabList.index(word)]=1 #对应索引标记1
        else:
            print("the word: %s is not in my Vocabulary!" %word)
    return returnVec

4.5.2 训练算法:从词向量计算概率

在这里插入图片描述
该函数的伪代码如下:
         计算每个类别中的文档数目
         对每篇训练文档:
                 对每个类别:
                           如果词条出现在文档中→ 增加该词条的计数值
                           增加所有词条的计数值
                 对每个类别:
                       对每个词条:
                           将该词条的数目除以总词条数目得到条件概率
          返回每个类别的条件概率

def trainNB0(trainMatrix,trainCategory):  #文档矩阵,文档类别标签组成的向量
    numTrainDocs=len(trainMatrix) #单个文档个数
    numWords=len(trainMatrix[0])
    pAbusive=sum(trainCategory)/float(numTrainDocs) #含有侮辱性总数/文档总数,即P(1)
    p0Denom=0.0
    p1Denom=0.0
    p0Num=zeros(numWords)
    p1Num=zeros(numWords)
    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=p1Num/p1Denom
    p0Vect=p0Num/p0Denom
    return p0Vect,p1Vect,pAbusive

该函数为统计单词列表中每个单词在0 和 1 两个分类中出现的概率,即P(w|c)
我们需要找出0和1两个分类中概率最大的单词(特征),可以粗略的用概率最大的单词来作为判断是否为某分类。

4.5.3 测试算法:根据现实情况修改分类器

          (1)利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,即计算p(w0|1)p(w1|1)p(w2|1)。如果其中一个概率值为0,那么最后的乘积也为0。为降低这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2。
          (2)多个概率相乘(<1)数值过小下溢四舍五入得到不正确答案,因此进行log处理
朴素贝叶斯分类函数

#
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

#
def testingNB():
    listOPosts,listClasses=loadDataSet()
    myVocabList=createVocabList(listOPosts)
    trainMat=[]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
    p0V,p1V,pAb=trainNB0(array(trainMat),array(listClasses))
    testEntry=['love','my','dalmation']
    thisDoc=array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
    testEntry=['stupid','garbage']
    thisDoc=array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))

4.5.4 准备数据:文档词袋模型

            将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-words model)。如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型(bag-of-words model)。
因此需要统计出现次数,而不是仅仅出现设置为1。

4.6 示例:使用朴素贝叶斯过滤垃圾邮件

4.6.1 准备数据:切分文本

(1)利用正则表达式切割,能够删除标点符号。
(2)利用长度判断是否为空格,删去空格并统一大小写。

import re
reg=re.compile('\\W+')
l=reg.split(s)
a=[per.lower() for per in l if len(per)>0]

4.6.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):       #26个文本
        wordList=textParse(open('spam\%d.txt' %i).read()) #返回单词向量
        docList.append(wordList)  #每行添加一个向量
        fullText.extend(wordList)
        classList.append(1)  #分类1
        wordList=textParse(open('ham\%d.txt' %i).read())       
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)  #分类0
    vocabList=createVocabList(docList) #转化为列表单词
    trainingSet=list(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(setOfWords2Vec(vocabList,docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0V,p1V,pSpam=trainNB0(array(trainMat),array(trainClasses))#由训练集计算出的P(w|c)
    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))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值