zoukankan      html  css  js  c++  java
  • 我眼中的朴素贝叶斯

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

    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))
        

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

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

  • 相关阅读:
    CVE-2017-10271
    [GKCTF2020]cve版签到
    [GXYCTF2019]禁止套娃 无参数RCE
    [护网杯 2018]easy_tornado
    记两道xctf上的web进阶区 反序列化
    msf卸载win defender
    Cron表达式详解
    Linux ifconfig只有lo没有别的网络的问题
    记一道文件上传
    【解决】手机安卓已经导入burp证书,但仍提示此证书并非来自被信任的机构
  • 原文地址:https://www.cnblogs.com/zhxuxu/p/9748414.html
Copyright © 2011-2022 走看看