朴素贝叶斯是一个概率模型,在数学上能用概率解释的模型一般被认为是好模型。
朴素贝叶斯常用于文本分类。
先介绍几个基础概念。
1. 概率
设x为符合某种特征的样本,H为某个假设,比如假设x属于类别c,那分类就是求这个假设发生的概率,即P(H|x)的大小。
P(H|X)是后验概率,或者说在条件X下,H的后验概率,就是在已知样本符合某种特征时,H发生的概率
P(H)是先验概率,或者说H的先验概率,就是所有样本中H发生的概率
P(X|H),P(X)同理
2. 条件概率
P(A|B)=P(AB)/P(B)
P(B|A)=P(AB)/P(A)
P(A|B)=P(B|A)P(A)/P(B)
经典案例
我们想计算含有单词drugs的邮件为垃圾邮件的概率
A为“这是封垃圾邮件”。P(A)也被称为先验信念(prior belief)。
计算方法是,统计训练集中垃圾邮件的比例。
如果我们的数据集每100封邮件有30封垃圾邮件,P(A)为30/100或0.3。
B表示“该封邮件含有单词drugs”。P(B)也被称为先验信念(prior belief)。
类似地,我们可以通过计算数据集中含有单词drugs的邮件数量得到P(B)。
如果每100封邮件中有10封邮件包含单词drugs,那么P(B)就为10/100或0.1。
P(B|A)指的是垃圾邮件中含有单词drugs的概率,计算起来也很容易,统计训练集中所有垃圾邮件的数量以及其中含有单词drugs的数量。
30封垃圾邮件中,如果有6封含有单词drugs,那么P(B|A)就为6/30或0.2。
现在,我们根据贝叶斯定理就能计算出P(A|B),得到含有drugs的邮件为垃圾邮件的概率。
把上面求出来的各项代入前面的贝叶斯公式,得到结果0.6。
这表明如果邮件中含有drugs这个词,那么该邮件为垃圾邮件的概率为60% 。
算法原理
1. 朴素贝叶斯之所以朴素,是其认为样本中属性间相互独立,体现在概率论上就是彼此是独立事件,故 P(AB)=P(A)P(B),所以文本就可以表示为P(X)=P(x1)P(x2)P(x3)...P(xk)
2. P(C|X)=P(X|C)P(C)/P(X)
P(X)表示样本集中含有某特征的样本的比例,是个常数,且对所有样本都一样,故可省略
P(C)其实也是个常数,但是要计算样本属于不同类别时要用不同类别的P(C),故不可省略
3. 计算出每个类别的概率,取概率最大对应的类别即可
粘张图吧,懒得写了
示例代码
import numpy as np def loadDataSet(): # 样本 postingList=[['my','dog','has','flea','problem','help','please'], ['maybe','not','take','him','to','dog','park','stupid'], ['my','dalmation','is','so','cute','I','love','him'], ['stop','posting','ate','my','steak','how','to','stop','him'], ['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 def createVocabList(dataSet): # 词向量集合 vocabSet=set([]) for document in dataSet: vocabSet=vocabSet|set(document) return list(vocabSet) def setOfWords2Vec(vocabList,inputSet): # word2vec 只有0 1 returnVec=[0]*len(vocabList) # 每个文档的大小与词典保持一致,此时returnVec是空表 for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)]=1 # 当前文档中有某个词条,则根据词典获取其位置并赋值1 else:print "the word :%s is not in my vocabulary" %word return returnVec def bagOfWords2Vec(vocabList,inputSet): # 词袋 出现次数 returnVec=[0]*len(vocabList) 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 def trainNB(trainMatrix,trainCategory): # 训练模型 trainMatrix---X, trainCategory--->Y numTrainDocs=len(trainMatrix) # 样本数量 numWords=len(trainMatrix[0]) # 属性集,次向量长度 pAbusive=sum(trainCategory)/float(numTrainDocs) # 统计侮辱性文档的总个数,然后除以总文档个数 P(A) #p0Num=zeros(numWords);p1Num=zeros(numWords) #p0Denom=0.0;p1Denom=0.0 p0Num=np.ones(numWords) p1Num=np.ones(numWords) p0Denom=2.0 p1Denom=2.0 for i in range(numTrainDocs): # 遍历样本 if trainCategory[i]==1: # 标签为1, 用于计算该类别下词的概率,P(X|A) p1Num+=trainMatrix[i] # 把属于同一类的文本向量相加,实质是统计某个词条在该类文本中出现频率 p1Denom+=sum(trainMatrix[i]) # 把侮辱性文档向量的所有元素加起来 else: # 标签为0, 用于计算该类别下词的概率,P(X|B) p0Num+=trainMatrix[i] p0Denom+=sum(trainMatrix[i]) # p1Vec=p1Num/float(p1Denom) # p0Vec=p0Num/float(p0Denom) p1Vec=np.log(p1Num/p1Denom) # 统计词典中所有词条在侮辱性文档中出现的概率 p0Vec=np.log(p0Num/p0Denom) # 统计词典中所有词条在正常文档中出现的概率 return pAbusive,p1Vec,p0Vec ### 注意:被注释掉的代码代表不太好的初始化方式,在那种情况下某些词条的概率值可能会非常非常小,甚至约 ### 等于0,那么在不同词条的概率在相乘时结果就近似于0 def classifyNB(vec2classify,p0Vec,p1Vec,pClass1): # 预测 # 参数1是测试文档向量,参数2和参数3是词条在各个类别中出现的概率,参数4是P(C1) p1=sum(vec2classify*p1Vec)+np.log(pClass1) # 这里没有直接计算P(x,y|C1)P(C1),而是取其对数这样做也是防止概率之积太小,以至于为0 p0=sum(vec2classify*p0Vec)+np.log(1.0-pClass1) # 取对数后虽然P(C1|x,y)和P(C0|x,y)的值变了,但是不影响它们的大小关系。 if p1>p0: return 1 else: return 0 if __name__ == '__main__': postingList,classVec = loadDataSet() vocab = createVocabList(postingList) setvec = [setOfWords2Vec(vocab, i) for i in postingList] bagvec = [bagOfWords2Vec(vocab, i) for i in postingList] pAbusive,p1Vec,p0Vec = trainNB(bagvec, classVec) for i in setvec: print classifyNB(i,p0Vec,p1Vec,pAbusive)
只是个示例,拿训练样本测试的。
注意在预测时,计算概率用了加法,本身应该是乘法的,但是因为取了log,乘法变加法,注意在计算P(xk)时直接取了log,所以在预测时直接sum了。
log 避免了因概率因子远小于1而连乘造成的下溢出。
还有一种避免0概率的方法叫拉普拉斯平滑,其实很简单,就是在每个类别的样本数上+1,那么样本最少是1,所以不会是0概率,注意每个类别加1,总样本要加类别数。
总结
朴素贝叶斯对小规模数据集表现很好,适合多分类,但是如果属性间相关性较强,表现不好。
参考资料:
https://blog.csdn.net/amds123/article/details/70173402
https://blog.csdn.net/li8zi8fa/article/details/76176597