Machine Learning---3--朴素贝叶斯

来源:互联网 发布:淘宝有一加的旗舰店吗 编辑:程序博客网 时间:2024/06/06 01:37

(1)贝叶斯分类的基础——贝叶斯定理

条件概率:    表示事件B已经发生的前提下,事件A发生的概率,叫做事件B发生下事件A的条件概率。其基本求解公式为:

                                                                                                                 

我们可以很容易直接得出P(A|B),P(B|A)则很难直接得出,但我们更关心P(B|A),贝叶斯定理就为我们打通从P(A|B)获得P(B|A)的道路。

      下面不加证明地直接给出贝叶斯定理:

                                                                                                                 

(2)朴素贝叶斯分类的原理与流程

朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。

 朴素贝叶斯分类的正式定义如下:

      1、设为一个待分类项,而每个a为x的一个特征属性。

      2、有类别集合

      3、计算

      4、如果,则

      那么现在的关键就是如何计算第3步中的各个条件概率。我们可以这么做:

      1、找到一个已知分类的待分类项集合,这个集合叫做训练样本集。

      2、统计得到在各类别下各个特征属性的条件概率估计。即

      3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:

      

      因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:

      

(3)Laplace校准

需要讨论的问题就是当P(a|y)=0怎么办,当某个类别下某个特征项划分没有出现时,就是产生这种现象,这会令分类器质量大大降低。为了解决这个问题,我们引入Laplace校准,它的思想非常简单,就是对没类别下所有划分的计数加1,这样如果训练样本集数量充分大时,并不会对结果产生影响,并且解决了上述频率为0的尴尬局面。

(4)Python实现

## 1、从文本构建词向量from math import logimport numpy as npdef loadDataSet():        #postingList: 进行词条切分后的文档集合    #classVec:类别标签            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,classVecdef createVocabList(dataSet):    vocabSet = set([])#使用set创建不重复词表库    for document in dataSet:        vocabSet = vocabSet | set(document) #创建两个集合的并集    return list(vocabSet) #返回所有文档中不重复词列表def setOfWords2Vec(vocabList, inputSet):    returnVec = [0]*len(vocabList)#创建一个所包含元素都为0的向量(创建与词汇表等长的向量)    #遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1    for word in inputSet:        if word in vocabList:            returnVec[vocabList.index(word)] = 1        else: print("the word: %s is not in my Vocabulary!" % word)    return returnVec#我们将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-words model)。#如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,#这种方法被称为词袋模型(bag-of-words model)。#在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。#为适应词袋模型,需要对函数setOfWords2Vec稍加修改,修改后的函数称为bagOfWords2VecMNdef bagOfWords2VecMN(vocabList, inputSet):    returnVec = [0]*len(vocabList)    for word in inputSet:        if word in vocabList:            returnVec[vocabList.index(word)] += 1    return returnVec## 2、训练贝叶斯分类器def trainNB0(trainMatrix,trainCategory):        #朴素贝叶斯分类器训练函数(此处仅处理两类分类问题)    #trainMatrix:文档矩阵    #trainCategory:每篇文档类别标签        numTrainDocs = len(trainMatrix)    numWords = len(trainMatrix[0])    pAbusive = sum(trainCategory)/float(numTrainDocs)    #初始化所有词出现数为1,并将分母初始化为2,避免某一个概率值为0(Laplace校正)    p0Num =np.ones(numWords); p1Num = np.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 = log(p1Num/p1Denom)#change to log()    p0Vect = log(p0Num/p0Denom)#change to log()    return p0Vect,p1Vect,pAbusivedef classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):        #分类函数    #vec2Classify:要分类的向量    #p0Vec, p1Vec, pClass1:分别对应trainNB0计算得到的3个概率        p1 = sum(vec2Classify * p1Vec) + log(pClass1)    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)    if p1 > p0:        return 1    else:         return 0        '''    #测试模型,该函数封装了之前所有操作def testingNB():    listOPosts,listClasses = loadDataSet()    myVocabList = createVocabList(listOPosts)    trainMat=[]    for postinDoc in listOPosts:        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))    #训练模型,注意此处使用array    p0V,p1V,pAb = trainNB0(np.array(trainMat),np.array(listClasses))    testEntry = ['love', 'my', 'dalmation']    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))    print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))    testEntry = ['stupid', 'garbage']    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))    print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))   '''if __name__== "__main__":    postingList,classVec=loadDataSet()  #获得训练集及类别    myVocabSet=createVocabList(postingList) #将训练集转为词向量    print(myVocabSet)    pre=setOfWords2Vec(myVocabSet, postingList[0])    print(pre)        #法一    trainMat=[]    for postinDoc in postingList:  #使用for循环来填充trainMat列表        trainMat.append(setOfWords2Vec(myVocabSet,postinDoc)    #p0V,p1V,pAb= trainNB0(trainMat,classVec)    #训练模型,注意此处使用array,将列表转为数组    p0V,p1V,pAb = trainNB0(np.array(trainMat),np.array(classVec)) #计算侮辱性文档概率及两个类别的概率    print(p0V)    print(p1V)    print(pAb)    testEntry = ['love', 'my', 'dalmation']    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))    print(testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))        #法二    #print(testingNB())





原创粉丝点击