朴素贝叶斯是一个基于概率论的算法,如下公式为贝叶斯准则:
它经常被用来进行文本分类,之所以被称为“naive”,是因为这个算法有两个假设,第一个假设是特征之间是相互独立的,第二个假设是每个特征是同等重要的,也就是说当利用这种算法进行文本分类的时候,不考虑文本中词汇之间的相互关系,以及重要性,但是实际上利用这种看上去比较扯淡的假设却收获了极其优秀的分类结果。
贝努利模型只考虑文本词汇是否出现而不考虑出现次数,这在最后的朴素贝叶斯分类器函数的编写上带来了很大的便利,几行就搞定输出。
下面来看代码实现:
(1)利用set方法构建集合
def loadDataset():
postList=[]
classVec=[]
return postList,classVec
def createVocablist(dataset):
vocalSet=set([])
for i in dataset:
vocalSet=vocalSet|set(i)
return list(vocalSet)
def setofWords2vec(vocalList,inputset):
returnVec=[0]*len(vocalList)
for i in inputset:
if i in vocalList:
returnVec[vocalList.index(i)]=1
else:
print("the word: %s is not in my Vocabulary!"% i)
return returnVec
(2)朴素贝叶斯分类器训练函数
def trainNB(trainMatrix,trainCategory):
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=log(p1num/p1Denom)
p0vect=log(p0num/p0Denom)
return p0vect,p1vect,pAbusive
由于概率值相乘的值都会很小,这里使用log函数避免下溢出,另外将所有的文本词汇出现次数初始化为1,将分母初始化为2,这里为什么分母是2在我理解看来无足轻重,也可以是1差别并不大,但是最常使用的是这种初始化方式。为什么只返回三个值呢,因为在最后的p0,p1比较中p(w),其中的w为词向量,为相同的分母可以直接略去。
(3)朴素贝叶斯分类函数
def classify(vec,p0vec,p1vec,p1):
p1=sum(vec*p1vec)+log(p1)
p2=sum(vec*p0vec)+log(1-p1)
if(p1>p2):
return 1
else:
return 0
虽然这段代码十分的精简,但是含义颇深,对于的vec*p1vec的含义实际上是贝努利模型的便捷性体现,因为vec只存在两个值0或者1,所以这里的乘法只具备数学意义,无法解释成其他的意义,具体数学推导不作说明。
上述完成了整个朴素贝叶斯的算法,下一章将介绍机器学习中最难的分类算法SVM,也是普遍认为使用和效果最好的分类器算法。