zoukankan      html  css  js  c++  java
  • 机器学习实战笔记--朴素贝叶斯(实例代码)

    #coding:utf-8
    from numpy import *
    #加载文档词向量数据以及相应文档类别,0表示正常言论,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','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 createVocabList(dataSet):
        '''
    功能:将已知类别文档中出现的词汇 存入到 所有词汇集合,相当于字典 返回其list类型
    
    输入数据类型:列表类型(列表中存储的是列表元素,每篇文档的词汇集合)
    输出数据类型:列表类型(字典)
    '''
        vocabSet = set([])
        for document in dataSet:
            vocabSet = vocabSet | set(document)
        return list(vocabSet)
    
    
    def setOfWords2Vec(vocabList,inputSet):
        '''
    功能:将输入的文档转成词向量形式,即在字典中所有词汇出现的词频数,出现为1,未出现为0.
    输入数据类型:列表类型(字典,存储所有词汇)
                  字符串(将要预测的留言)
    输出数据类型:列表类型(词向量)
    
    '''
        returnVec =[0]*len(vocabList)
        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):
        '''
    功能:计算属于1类对应下的所有词汇出现的词频数(词向量形式),用p1Num存放。0类一样。
          计算属于1类的所有词汇总数,用p1Denom存放。0类一样。
          返回字典词汇的条件概率p0Vect,p1Vect以及文档属于1类的概率pAbusive。p0Vect= [p(w1|c1),p(w2|c1)...p(wn|c1)]
          
    输入的数据类型:array列表类型(样本词向量)
                    array列表类型(样本对应的类别)
    输出的数据类型:列表类型(字典词汇的条件概率0)
                    列表类型(字典词汇的条件概率1)
                    浮点数(文档属于1类的概率)
    '''
        numTrainDocs = len(trainMatrix)
        numWords = len(trainMatrix[0])
        pAbusive = sum(trainCategory)/float(numTrainDocs)
        p0Num = ones(numWords)
        p1Num = ones(numWords)
        p0Denom = 2.0
        p1Denom = 2.0
        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
    
    def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
        '''
    功能:计算贝叶斯概率公式,忽略分母(因为每个类别的分母相等)。计算技巧是分子变形,使相乘的n个数转换为log每个数相加
          返回留言板的预测类别。
          
    输入数据类型:列表(词向量形式)
                  列表(字典词汇的条件概率0)
                  列表(字典词汇的条件概率1)
                  浮点数(文档属于1类的概率)
    输出数据类型:整数(预测类别)
    '''
        p1 = sum(vec2Classify * p1Vec) + log(pClass1)
        p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
        if p1>p0:
            return 1
        else:
            return 0
    
    def tesingNB():
        '''
    功能:调用以上定义的功能函数,训练分类器然后测试两条数据
    '''
        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)
        #以下这个例子可以作为感兴趣的点。贝叶斯中的0类,1类正负抵消。并不是出现侮辱性词就判定为侮辱类
    
        testEntry = ['love','my','dalmation','stupid']
        thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
        print testEntry,'Classified as :',classifyNB(thisDoc,p0V,p1V,pAb)
    朴素贝叶斯实例

       朴素贝叶斯算法之所以称为朴素是因为有个前提假设条件:对于给定样本各属性相互条件独立。也就是说给定一句话 d1=“苹果很好吃”,我们来判定这句话是食物类还是器材类,那如果用朴素贝叶斯算法,就假设了这句话里的每个词(特征)w1=“苹果”,w2=“很”,w3=”好吃”出现的概率是相互独立的,没有依赖的。但我们知道实际上这条假设并不能真正反映现实的规律,因为“苹果”后面往往有很大概率会出现“好吃”,也就是 p(苹果,好吃) = p(苹果)* p(好吃 | 苹果),但我们现在就假设 p(苹果,好吃) = p(苹果)* p(好吃) 。

      朴素贝叶斯分类的目标就是实际上已知训练数据,求出它属于哪个类的概率值最大就预测为哪个类。就拿上面的例子所说,食物类是C1,器材类是C2,P(C1|d1)>P(C2|d1) 则把d1判定为C1类,反之。利用贝叶斯公式可知 P(C1|d1) = P(d1|C1)P(C1)/P(d1),目标是比较P(C1|d1)和P(C2|d1)大小,分母是相同的可以忽略。近似比较P(d1|C1)P(C1)和P(d1|C2)P(C2),两个类别的先验概率P(C1)和P(C2)可以根据训练数据集求出,由于以上的假设得 P(d1|C1)=P(w1|C1)P(w2|C1)P(w3|C1),而已知类别下的各个特征条件概率也可以根据训练数据集统计出来,比如P(w1|C1)具体计算就是在C1类别下w1出现的次数/C1类别下出现所有词的总次数。这样就可以通过每项的计算来进行近似比较了。那如果w1在某类下出现的次数为0呢?岂不是条件概率P(d1|C1)就为0了,别急,下面会介绍拉普拉斯估计。下面给出形式化的数学表述:

      (据听说数学是世界上最好的语言之一)

           设训练样本集分为k类,记为 C= {C1,C2 ,…, Ck},则每个类的先验概率为P(Ci),i=1,2,...,k, 其值为Ci类的样本数除以训练集总样本数n。对于新样本d,其属于Ci类的条件概率是P(d|Ci)。根据贝叶斯定理,Ci类的后验概率为:

      P(d)对于所有类均为同一常数,可以忽略。为避免P(Ci)等于0,采用拉普拉斯概率估计:

      其中|C|为训练集中类的数目,|Dci|为训练集中属于类Ci的文档数,|Dc|为训练集包含的总文档数。

      对于待分类文本文档d,本文采用向量空间模型,其基本思想是将每一个文本表示为一个向量d= (w1,...,wm),m是d的特征词个数。 贝叶斯算法假设各特征词相互独立。

      朴素贝叶斯分类器将未知样本归于哪类的依据,如下:

       

     

  • 相关阅读:
    最近几周的总结
    做游戏
    枚举 结构 .....
    抽象类
    面向对象过程
    构造函数 对象关系
    .net 第二周学习
    。net初学
    CSS基本知识点(01)
    C#之ADO.NET基本知识点(01)
  • 原文地址:https://www.cnblogs.com/hithink/p/6424467.html
Copyright © 2011-2022 走看看