• 朴素贝叶斯小结


    朴素贝叶斯是一种简单的分类算法,称它“朴素”是因为,整个形式化过程只做最原始 最简单的假设。朴素贝叶斯的核心思想是:对于待分类项,求解此待分类项在各个类别中出现的概率,哪个类别概率最大,则认为此待分类项就属于那个类别。

    朴素贝叶斯是贝叶斯决策理论的一部分

    1 朴素贝叶斯原理

    1.1 概率论知识

    既然朴素贝叶斯是求概率,首先介绍概率论的知识。假设(X)(Y)相互独立,则有条件独立公式:

    [P(X,Y)=P(X)P(Y) ]

    条件概率公式:

    [P(Y|X)=frac{P(X,Y)}{P(X)} ]

    [P(X|Y)=frac{P(X,Y)}{P(Y)} ]

    全概率公式:

    [P(X)=sum_{k}P(X|Y=Y_{k})P(Y_{k}) ]

    其中,(sum_{k}P(Y_{k})=1)

    1.2 贝叶斯定理

    朴素贝叶斯是贝叶斯决策理论的一部分,讲朴素贝叶斯前,有必要了解一下贝叶斯决策理论。贝叶斯理论解决的是这样的问题:已知某条件概率,如何得到两个事件交换后的概率呢?也就是,已知(P(X|Y))的情况下如何求得(P(Y|X))?于是,提出贝叶斯定理:

    [P(Y|X)=frac{P(X|Y)P(Y)}{P(X)} ]

    [P(Y_{k}|X)=frac{P(X|Y_{k})P(Y_{k})}{sum_{k}P(X|Y=Y_{k})P(Y_{k})} ]

    2 朴素贝叶斯算法

    输入:训练集有(m)个样本,每个样本有(n)个特征,共有(K)个特征输出类别,训练集表示为:(T=left { left ( x_{1},y_{1} ight ),left ( x_{2},y_{2} ight ),cdots,left ( x_{n},y_{n} ight ) ight },其中)x_{i}=left ( x_{i}{(1)},x_{i}{(2)},cdots,x_{i}^{n} ight ){T}$,$x_{i}{(j)}(是第)i(个样本的第)j(个特征,)yepsilon left { c_{1},c_{2},cdots,c_{K} ight }( **输出:**待测试实例)x_{(test)}$的分类

    算法流程:
    step1 计算(Y)(K)个先验概率

    [P(Y=c_{k}) ]

    step2 计算条件概率

    [P(X=x|Y=c_{k})=P(X^{(1)}=x^{(1)},cdots, X^{(n)}=x^{(n)}|Y=c_{k}) ]

    上式的参数是指数级别,无法计算。所以根据特征条件独立假设,可以化简为下式

    [P(X=x|Y=c_{k})=prod_{j=1}^{n}P(X^{(j)}=x^{(j)}|Y=c_{k}) ]

    step3 根据贝叶斯定理,计算后验概率

    [P(Y=c_{k}|X=x)=frac{P(X=x|Y=c_{k})P(Y=c_{k})}{sum_{k}P(X=x|Y=c_{k})P(Y=c_{k})} ]

    (P(X=x|Y=c_{k})=prod _{j=1}^{n}P(X^{(j)}=x^{(j)}|Y=c_{k}))得到

    [P(Y=c_{k}|X=x)=frac{prod_{j=1}^{n}P(X^{(j)}=x^{(j)}|Y=c_{k})P(Y=c_{k})}{sum_{k}prod_{j=1}^{n}P(X^{(j)}=x^{(j)}|Y=c_{k})P(Y=c_{k})} ]

    由于分母相同,上式简化为

    [P(Y=c_{k}|X=x)=prod_{j=1}^{n} P(X^{(j)}=x^{(j)}|Y=c_{k})P(Y=c_{k}) ]

    step4 计算(X_{(test)})的类别

    [y_{(test)}=arg max_{c_{k}}prod_{j=1}^{n} P(X^{(j)}=x^{(j)}_{(test)}|Y=c_{k})P(Y=c_{k}) ]

    3 朴素贝叶斯代码实现

    #bayes.py
    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]  #1代表侮辱性文字 0代表正常言论
        return postingList, classVec #postingList表示进行词条切分后的文档集合 classVec表示类别标签集合
    
    def createVocabList(dataSet): #创建一个包含在所有文档中出现的不重复词的列表(获取词表)
        vocabSet = set([])  #创建一个空集 set返回一个不重复词表
        for document in dataSet: #将每篇文档返回的新词集合添加到该集合vocabSet中
            vocabSet = vocabSet | set(document)  #创建两个集合的并集
        return list(vocabSet)
    
    def setOfWords2Vec(vocabList, inputSet): #参数vocabList代表词汇表 inputSet代表输入文档 函数最后输出文档向量 向量每个元素为1或0 表示词汇表中的单词在输入文档中是否出现
        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)
        return returnVec
    
    #训练算法:朴素贝叶斯分类器训练函数
    def trainNB0(trainMatrix, trainCategory): #trainMatrix代表文档矩阵 trainCategory代表每篇文档类别标签所构成的向量
        numTrainDocs = len(trainMatrix)
        numWords = len(trainMatrix[0])
        pAbusive = sum(trainCategory)/float(numTrainDocs)  #计算文档属于侮辱性文档的概率
        #p0Num = zeros(numWords)  #初始化概率
        #p1Num = zeros(numWords)
        #p0Denom = 0.0
        #p1Denom = 0.0
        p0Num = ones(numWords)
        p1Num = ones(numWords)
        p0Denom = 2.0
        p1Denom = 2.0
    
        for i in range(numTrainDocs): #遍历训练集trainMatrix中的所有文档
            if trainCategory[i] == 1:  #向量相加 某个词语在文档中出现 则该词对应个数p1Num或p0Num加1 同时在所有文档中 该文档的总词数也对应加1
                p1Num += trainMatrix[i]
                p1Denom += sum(trainMatrix[i])
            else:
                p0Num += trainMatrix[i]
                p0Denom += sum(trainMatrix[i])
        #p1Vect = p1Num/p1Denom #对每个元素除以该该类别的总词数 得出在给定文档类别条件下词汇表中单词的出现概率
        #p0Vect = p0Num/p0Denom
        p1Vect = log(p1Num / p1Denom)
        p0Vect = log(p0Num / p0Denom)
        return p0Vect,p1Vect,pAbusive  #返回两个向量 一个概率
    
    #测试算法:朴素贝叶斯分类函数
    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 bagOfWords2VecMN(vocabList, inputSet):
        returnVec = [0]*len(vocabList)
        for word in inputSet:
            if word in vocabList:
                returnVec[vocabList.index(word)] += 1
        return returnVec
    
    #封装函数所有操作
    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))
    
    #文件解析及垃圾邮件测试函数
    def textParse(bigSting):  #接受一个大字符串并将其解析为字符串列表
        import re
        listOfTokens = re.split(r'W*', bigSting)
        return [tok.lower() for tok in listOfTokens if len(tok) > 2]  #去掉少于两个字符的字符串 并将所有字符串转换为小写
    
    def spamTest():  #对贝叶斯垃圾邮件分类器进行自动化处理
        docList=[]; classList = []; fullText =[]
        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())
            #print(i)
            docList.append(wordList)
            fullText.extend(wordList)
            classList.append(0)
        vocabList = createVocabList(docList)#create vocabulary
        trainingSet = list(range(50)); testSet=[]           #create test set
        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:#train the classifier (get probs) trainNB0
            trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
            trainClasses.append(classList[docIndex])
        p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
        errorCount = 0
        for docIndex in testSet:        #classify the remaining items
            wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
            if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
                errorCount += 1
                print("classification error",docList[docIndex])
        print('the error rate is: ',float(errorCount)/len(testSet))
    
    #运行效果
    >>> import bayes
    >>> listOPosts, listClasses = bayes.loadDataSet()
    >>> myVocaList = bayes.createVocabList(listOPosts)
    >>> myVocaList
    ['garbage', 'ate', 'park', 'stupid', 'dalmation', 'him', 'not', 'how', 'cute', 'posting', 'food', 'has', 'so', 'please', 'love', 'my', 'to', 'steak', 'dog', 'quit', 'licks', 'buying', 'stop', 'take', 'mr', 'I', 'worthless', 'maybe', 'is', 'flea', 'problems', 'help']
    
    >>>bayes.setOfWords2Vec(myVocaList, listOPosts[0])
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]
    
    >>>from numpy import *
    >>>import imp
    >>>import bayes
    >>>imp.reload(bayes)
    >>> myVocabList = bayes.createVocabList(listOPosts)
    >>> trainMat = []
    for postinDoc in listOPosts:
    ...  trainMat.append(bayes.setOfWords2Vec(myVocabList, postinDoc))
    ...
    >>> p0V,p1V,pAb = bayes.trainNB0(trainMat, listClasses)
    >>> pAb
    0.5
    >>> p0V
    array([ 0.        ,  0.04166667,  0.        ,  0.        ,  0.04166667,
            0.08333333,  0.        ,  0.04166667,  0.04166667,  0.        ,
            0.        ,  0.04166667,  0.04166667,  0.04166667,  0.04166667,
            0.125     ,  0.04166667,  0.04166667,  0.04166667,  0.        ,
            0.04166667,  0.        ,  0.04166667,  0.        ,  0.04166667,
            0.04166667,  0.        ,  0.        ,  0.04166667,  0.04166667,
            0.04166667,  0.04166667])
    >>> p1V
    array([ 0.05263158,  0.        ,  0.05263158,  0.15789474,  0.        ,
            0.05263158,  0.05263158,  0.        ,  0.        ,  0.05263158,
            0.05263158,  0.        ,  0.        ,  0.        ,  0.        ,
            0.        ,  0.05263158,  0.        ,  0.10526316,  0.05263158,
            0.        ,  0.05263158,  0.05263158,  0.05263158,  0.        ,
            0.        ,  0.10526316,  0.05263158,  0.        ,  0.        ,
            0.        ,  0.        ])
    myVocabList
    ['garbage', 'ate', 'park', 'stupid', 'dalmation', 'him', 'not', 'how', 'cute', 'posting', 'food', 'has', 'so', 'please', 'love', 'my', 'to', 'steak', 'dog', 'quit', 'licks', 'buying', 'stop', 'take', 'mr', 'I', 'worthless', 'maybe', 'is', 'flea', 'problems', 'help']
    
    imp.reload(bayes)
    <module 'bayes' from 'D:\Python\Mechine_learning\Bayes\bayes.py'>
    >>> bayes.testingNB()
    ['love', 'my', 'dalmation'] classified as:  0
    ['stupid', 'garbage'] classified as:  1
    

    4 朴素贝叶斯小结

    贝叶斯优缺点:
    优点
    朴素贝叶斯模型有稳定的分类效率。
    对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,可以一批批的去增量训练。
    对缺失数据不太敏感,算也比较简单,常用于文本分类。
    缺点
    朴素贝叶斯模型的特征条件独立假设在实际应用中往往是不成立的。
    如果样本数据分布不能很好的代表样本空间分布,那先验概率容易测不准。对输入数据的表达形式很敏感。

    ***参考:机器学习实战 统计学习方法 朴素贝叶斯算法原理小结 ***

  • 相关阅读:
    系统运行性能监控日志
    iptables 操作
    访问dubbo没有权限,通过ip进行跳转服务器,并通过有权限服务器代理访问
    乐观锁
    ES的优化布局
    Docker壳的配置笔记
    expect 实现iterm2自动加载pem登录跳板机
    mybaits-spring demo 记
    Java中volatile修饰符,不稳定标记的用法笔记
    用intellj 建一个spring mvc 项目DEMO
  • 原文地址:https://www.cnblogs.com/eugene0/p/11421318.html
Copyright © 2020-2023  润新知