我眼中的朴素贝叶斯

Posted zhxuxu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我眼中的朴素贝叶斯相关的知识,希望对你有一定的参考价值。

既然要用到贝叶斯公式,首先给出贝叶斯公式

P(A|B)=P(B|A)P(A)/P(B)

数学含义:

P(A)是先验概率,可以通过计算获得

P(B|A)是条件概率,意识是在A发生的条件下B发生的概率

P(B)是用于归一化的“证据”因子,对于给定的样本B,P(B)与类标记无关

P(A|B)就是后验概率,也是需要我们根据P(B|A),P(A)求的

这个准则有什么用呢?接下来给一个例子

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

目标是实现自动检测输入的文档是侮辱性词还是非侮辱性词

首先用图来描绘整个过程,和对贝叶斯公式的简单运用

创建训练集:

假如你有6个文档,并且知道他们个属于什么类型(侮辱/一般)词

技术分享图片

0表示一般词,1表示侮辱词,首先把这些词汇总在一起构建一个无重复的词库

技术分享图片

有了词库以后我们要制作训练集,就要把6六个文档用词向量的形式比表示,怎么做呢?,就用到了无重复的词库,把6个文档分别与词库比较,有就标记为1,无则为0,就得到只有01的矩阵,它的列长与词库的长度相同

技术分享图片

这就是训练集,接下来训练

训练过程:

词矩阵:[Wi]

c1表示辱骂型词,c0表示一般词

训练的过程是要求出每一词的条件分布P([wi]|c1),P([wi]|c0)

 P([wi]|c1):已知词wi是辱骂性词的条件下,它的概率是多少,概率越高表示它出现的次数越多,表示它越可能是辱骂性词

P([wi]|c0):相同可知

要求这两个条件概率,首先要把训练样本根据已知标签分成两类c1,c0,然后再求每一词出现的概率,所以最后得到两个条件概率矩阵。

技术分享图片

 

技术分享图片

得到两个矩阵后,相当于训练好的模型,但怎么实现分类呢?在回顾一下贝叶斯准则

P(cj|[wi])=p([Wi]|c1)*P(c1)/P([wi])

P(cj|[wi]):含义是已知词wi,则它是(侮辱性词/非侮辱性)的概率是多少,这就是我们要求的,求得这个概率就能确定它的分类

[Wi]是词矩阵,且假设每一个词都是相互独立,这样就简化了问题,这也是为什么叫朴素贝叶斯。

p([Wi]|c1) = p(W1|c1)*p(W2|c1)*....p(Wn|c1)

p([Wi]|c0) = p(W1|c0)*p(W2|c0)*....p(Wn|c0)

所以

P(c1|[wi]) = p(W1|c1)*p(W2|c1)*....p(Wn|c1)P(c1)

P(c0|[wi]) = p(W1|c0)*p(W2|c0)*....p(Wn|c0)P(c0)

比较P(c1|[wi]),P(c0|[wi])大小

if P(c1|[wi])>P(c0|[wi])

说明是侮辱性词的概率大

else

是一般性词

测试:

假如输入一个不知道类型的文档,根据上面的词库建立它是词向量,分别与上面的两个条件概率向量相乘,计算条件贝叶斯概率即可

代码:

#coding=utf-8

from numpy import *

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]]
    #1代表侮辱性文字,0代表正常言论
    classVec = [0,1,0,1,0,1]
    return postingList,classVec

def createVocabList(dataSet):
    vocabSet = set([])
    #把词数据集去重复
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)
   
def setOfWords2Vec(vocabList,inputSet):
    #构建一个长度和vocabList一样的零向量
    returnVec =[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            #如果这个词在词表中有,则词向量中相应位置值设为1
            #vocabList.index(word) 返回的是词word在vocabList中的位置下标
            returnVec[vocabList.index(word)] = 1
        else:
            print ("the word :%s is not in my Vocabulary" %word)
    return returnVec
    
    
#朴素贝叶斯分类器训练trainMaxtrix训练矩阵,trainCategory标签
def trainNB0(trainMaxtrix,trainCategory):
    #行数
    numTrainDocs = len(trainMaxtrix)
    #列数
    numWords = len(trainMaxtrix[0])
    #侮辱性文档所占概率P(c1)
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    #为了防止其中一个概率为零,导致乘积为零,初始化分子为1,分母为2
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    #遍历文档,每一行表示一个文档
    for i in range(numTrainDocs):
        #1表示正常言论文档,否则辱骂言论文档
        if trainCategory[i] == 1:
            #统计每个词出现的次数
            p1Num += trainMaxtrix[i]
            #辱骂词的总个数
            p1Denom +=sum(trainMaxtrix[i])
        else:
            p0Num += trainMaxtrix[i]
            p0Denom +=sum(trainMaxtrix[i])
    #p([Wi]|c1) = p(W1|c1)*p(W2|c1)*....p(Wn|c1)  因为相互独立
    #p1Vect = p1Num/p1Denom,为了防止许多小数相乘下溢,于是log一下
    p1Vect = log(p1Num/p1Denom)
    #p([Wi]|c0) = p(W1|c0)*p(W2|c0)*....p(Wn|c0)
    #p0Vect = p0Num/p0Denom
    p0Vect = log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive
    
#朴素贝叶斯分类器函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    #p([Wi]|c1)*P(c1) = P(c1|[wi])*P(w) 根据贝叶斯公式
    #P(c1|[wi])意思是已知词wi,则它是(侮辱性词/非侮辱性)的概率是多少
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)
    #p([Wi]|c0)*P(c0) = P(c0|[wi])*P(w)
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1 > p0:
        return 1;
    else:
        return 0;

def testingNB():
    listOPosts,listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    print("myVocabList",myVocabList)
    trainMat = []
    #把文档转换成词向量,生成一个二维向量矩阵trainMat
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
    print("trainMat",trainMat)
    p0V,p1V,pAb = trainNB0(trainMat,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))
    

代码来至机器学习实战,我做了详细的注释,结合上面的图过程可以理解

主要还帮助理解的贝叶斯公式到底是怎么实现分类的。


以上是关于我眼中的朴素贝叶斯的主要内容,如果未能解决你的问题,请参考以下文章

朴素贝叶斯算法简介及python代码实现分析

干货 | 朴素贝叶斯python代码实现

机器学习:贝叶斯分类器——高斯朴素贝叶斯分类器代码实现

朴素贝叶斯分类算法介绍及python代码实现案例

Matlab 朴素贝叶斯

朴素贝叶斯并不朴素