目录
朴素贝叶斯( Naive Bayesian algorithm)是有监督学习的一种分类算法,它基于“贝叶斯定理”实现,该原理的提出人是英国著名数学家托马斯·贝叶斯。贝叶斯定理是基于概率论和统计学的相关知识实现的,因此在正式学习“朴素贝叶斯算法”前,我们有必要先认识“贝叶斯定理”。
一.贝叶斯定理
通常,事件 A 在事件 B 发生的条件下与事件 B 在事件 A 发生的条件下,它们两者的概率并不相同,但是它们两者之间存在一定的相关性,并具有以下公式(称之为“贝叶斯公式”):
二.条件概率
条件概率是概率论中一个重要且实用的概念。
所考虑的是在一个事件已经发生的条件下,另一个事件所发生的概率,记为P(A|B),它与P ( A ) 是不同的两类概率。设A 与B 是样本空间Ω中的两事件,若P ( B ) > 0 ,则称
性质:条件概率是概率,即若设P ( B ) > 0 ,则
(1)P ( A ∣ B ) ⩾ 0 , A ∈ F
(2)P ( Ω ∣ B ) = 1
(3)若F中的互不相容,则
三. 先验概率
在贝叶斯统计推断中,先验概率是在收集新数据之前事件发生的概率。 这是在进行实验之前根据当前知识对结果可能性进行的最佳理性评估。
事件A发生的先验概率记作:P ( A )
先验概率是事件还没有发生,根据以往的经验来判断事件发生的概率。
例子:扔一个硬币,在扔之前就知道正面向上的概率为0.5。这是根据我们之前的经验得到的。这个0.5就是先验概率。
四. 后验概率
在贝叶斯统计中,后验概率是在考虑新信息之后事件发生的修正或更新概率。 后验概率通过使用贝叶斯定理更新先验概率来计算。 用统计术语来说,后验概率是假设事件B已经发生的情况下事件A发生的概率。
(贝叶斯定理公式)给定B发生的情况下,计算A发生后验概率的公式:
A,B为事件。
P(B|A)是假设A为真,B发生的概率。
P(A)和P(B)是A和B相互独立发生的概率。
五. 朴素贝叶斯分类
朴素:朴素贝叶斯算法是假设各个特征之间相互独立,也是朴素这词的意思,那么贝叶斯公式中的P(X|Y)可写成:
朴素贝叶斯公式:
朴素贝叶斯分类器:朴素贝叶斯分类器(Naïve Bayes Classifier)采用了“属性条件独立性假设” ,即每个属性独立地对分类结果发生影响。为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为:
其中d为属性数目, 为 在第 个属性上的取值。
六 . 朴素贝叶斯实现垃圾邮箱分类
1.数据集准备
2.将词表转换成向量
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] # 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):
returnVec = [0] * len(vocabList) # 创建一个等长向量并设置为0
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1 # 若出现了单词表中的单词,则将对应值设置为1
else:
print("单词:%s 不存在!" % word)
return returnVec
# 测试函数效果
# 创建实验样本
listPosts, listClasses = loadDataSet()
print('数据集\n', listPosts)
# 创建词汇表
myVocabList = createVocabList(listPosts)
print('词汇表:\n', myVocabList)
# 输出文档向量
print(setOfwords2Vec(myVocabList, listPosts[5]))
3.词集模型
为输入的邮件构造单词集合
#词集模型
def setOfWord2Vec(vocabList,inputSet):
returnVec=zeros(len(vocabList))
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)]=1
else:
print("这个单词不在所有的单词向量里面")
return returnVec
4.词袋模型
#词袋模型
def bagOfword2VecMN(vocabList,inputSet):
returnVec=[0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)]+=1
return returnVec
5.朴素贝叶斯函数
#朴素贝叶斯训练函数
def trainB0(trainMatrix,trainCategory):
numTrainDocs=len(trainMatrix)
numwords=len(trainMatrix[0])
#对于category为0,1 才可以使用sum
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
6.朴素贝叶斯分类函数
#朴素贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
p1=sum(vec2Classify*p1Vec)+log(pClass1)
p0=sum(vec2Classify*p0Vec)+log(1-pClass1)
if p1>p0:
return 1
else:
return 0
7.提取单词
#将输入的文本字符串分割成单词list
def textParse(bigString):
listOfTokens=re.split(r'\W*',bigString)
return [tok.lower() for tok in listOfTokens if len(tok)>2]
8.垃圾邮件测试函数
def spamTest():
docList=[]
classList=[]
fullText=[]
filenameList1=listdir("email/train")
for name in filenameList1:
wordList=textParse(open("email/train/"+name).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
filenameList2=listdir("email/test")
for name in filenameList2:
wordList = textParse(open("email/test/"+name).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList=createVocabList(docList)
trainingSet=list(range(len(docList)))
testSet=[]
for i in range(int(0.2*len(docList))):
randIndex=int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
trainMat=[]
trainClasses=[]
for docIndex in trainingSet:
trainMat.append(setOfWord2Vec(vocabList,docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam=trainB0(array(trainMat),array(trainClasses))
errorCount=0
for docIndex in testSet:
wordVector=setOfWord2Vec(vocabList,docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam)!=classList[docIndex]:
errorCount+=1
print (r"垃圾邮件准确率:",float(errorCount/float(len(testSet))))
运行结果
七. 总结
朴素贝叶斯算法优缺点:
优点:在数据较少的情况下仍然有效,可以处理多类别问题
缺点:对于输入数据的准备方式较为敏感;由于朴素贝叶斯的“朴素”特点,所以会带来一些准确率上的损失
注意:使用拉普拉斯平滑解决零概率问题;
对乘积结果取自然对数避免下溢出问题,采用自然对数进行处理不会有任何损失。