(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 log import 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的向量(创建与词汇表等长的向量)#遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1else: 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)] += 1return 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 1else: return 0'''#测试模型,该函数封装了之前所有操作 def testingNB():listOPosts,listClasses = loadDataSet()myVocabList = createVocabList(listOPosts)trainMat=[]for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))#训练模型,注意此处使用arrayp0V,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())