机器学习实战-朴素贝叶斯算法

朴素贝叶斯概述

朴素贝叶斯也是一个强大的分类算法。其基本原理:假设现在有1,2,3,3种类别,现有一个数据a,其属于这个3种类别的概率分别为 p1(a),p2(a),p3(a) 。如果这3个概率中 p1(a) 最大,那么就把数据a归为1类。
这道理好简单啊,就算我们猜谜语也会猜一个可能性最大的嘛~~~
果然很朴素啊,但是呢,这里还是有一个问题的,这里的3个概率是怎么计算出来的呢?

条件概率

为了计算概率,就得翻出概率论的知识了。
假设现有数据 w=w0+w1+...+wn ,好多维啊。。类别有 c={c1,c2} 2种类别。
那么属于c1,c2的概率就可以表示为:
p(c1|w)=p(w|c1)p(c1)p(w)
p(c2|w)=p(w|c2)p(c2)p(w)
如果:
p(c1|w)>p(c2|w) , 那么w属于c1类。
p(c1|w)<p(c2|w) , 那么w属于c2类。
推广到多个类别:

p(ci|w)=p(w|ci)p(ci)p(w)

对于不同的类别,计算该公式,比较大小就ok了。这里的计算,其实只需要计算分子,因为分母部分对于任何类别来说都是一样的。分子大就归到哪一类。
这里以《机器学习实战》这本书上的例子为例。关于论坛留言,是否是侮辱性的判断。
计算 p(ci)
这里的 p(ci) 就是 ci 类文档数除以文档总数。
计算 p(w|ci)
p(w|ci) 的计算相对麻烦点,这里就要用到朴素贝叶斯的假设了,这里把w展开,可以写成 p(w0,w1,w2,...,wn|ci) ,这里假设所有的词相互独立(显然是不成立,很多词的出现是有关联的,所以这叫朴素贝叶斯,朴素的内涵在于此)。有了这个假设,上面的概率可以转化为 p(w0|ci)p(w1|ci)...p(wn|ci) ,这个公式看起来没简化多少,其实计算的时候会简单很多。
分解开来,单个拎出来看, p(w0|ci) 可以理解为w0这个词在ci这种文档中出现的概率,那么只要把ci文档中出现w0词数除以所有的词数即可。

Ok,顺利得到 p(w|ci)p(ci) 。我们就可以比较 p(ci|w) 大小来归类了。

code

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']]
    classvec=[0,1,0,1,0,1]
    return postingList,classvec
#生成一个文本集合,包含所有出现的词
def createvocalist(dataSet):
    vocaset=set([])
    for document in dataSet:
        vocaset=vocaset | set(document)
    return list(vocaset)
#把每个文档的词对应文本集合,映射成向量,如:[1,0,1,0,0...]
def setofWord2vec(vocalist,inputSet):
    returnVec=[0]*len(vocalist)
    for word in inputSet:
        if word in vocalist:
            returnVec[vocalist.index(word)] =1
        else:
            print "the word : %s is not in ..." % word
    return returnVec

def trainNB0(trainMatrix,trainclass):
    numdocs=len(trainMatrix)
    numWords=len(trainMatrix[0])
    #trainclass只有 0,1数据,求和相当于计算A=1的数量,再除以总数就是pA
    pA=sum(trainclass)/float(numdocs)
    p1num=ones(numWords)
    p0num=ones(numWords)
    p1sum=2.0
    p0sum=2.0
    for i in range(numdocs):
        if trainclass[i] == 1:
            p1num+=trainMatrix[i]#计算单个词出现的数量
            p1sum+=sum(trainMatrix[i])#计算所有词出现的数量
        else:
            p0num+=trainMatrix[i]
            p0sum+=sum(trainMatrix[i])
    p1vec=log(p1num/p1sum)#这里相当于前面分子左边的部分,在c1类别下,wi出现的概率
    p0vec=log(p0num/p0sum)
    return p0vec,p1vec,pA

def classifyNB(vec2class,p0Vec,p1Vec,pClass):
    #这里的求和有点奇怪,因为按照公式是所有词出现的概率相乘,然而这里却是求和,是因为前面用log来计算了。
    p1=sum(vec2class*p0Vec)+log(pClass)
    p0=sum(vec2class*p1Vec)+log(1.0-pClass)
    if p1>p0:
        return 1
    else:
        return 0
#测试分类
def testingNb():
    listdoc,listclass=loadDataSet()
    allwordlist=createvocalist(listdoc)
    trainMat=[]
    for doc in listdoc:
        trainMat.append(setofWord2vec(allwordlist,doc))
    p0v,p1v,pA=trainNB0(trainMat,listclass)
    testdoc=['love','my','jack']
    testdocvec=setofWord2vec(allwordlist,testdoc)
    print testdoc,'classified as:',classifyNB(testdocvec,p0v,p1v,pA)

end

参考:
《机器学习实战》

你可能感兴趣的:(Machine,Learning,机器学习)