朴素贝叶斯算法
(一)基本概念
贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。
这个定理解决了现实生活里经常遇到的问题:已知某条件概率,如何得到两个事件交换后的概率,也就是在已知P(A|B)的情况下如何求得P(B|A)。这里先解释什么是条件概率:
表示事件B已经发生的前提下,事件A发生的概率,叫做事件B发生下事件A的条件概率。其基本求解公式为:
。
下面不加证明地直接给出贝叶斯定理:
优点 :数据少时仍有效,处理多分类,
缺点 :对输入数据的准备方式较为敏感
适合的数据类型: 标称型
设由(x,y)表示的数据点,分类c,有:
原理及简单计算介绍,以下引用自(感谢):《机器学习实战》读书笔记5:朴素贝叶斯分类器的原理
假如我们要为一个疾病诊断系统构建一个贝叶斯分类器。首先,我们有如下训练集:
职业 | 症状 | 疾病 |
---|---|---|
矿工 | 咳嗽 | 肺炎 |
矿工 | 头痛 | 感冒 |
护士 | 咳嗽 | 肺结核 |
护士 | 头痛 | 肺炎 |
矿工 | 咽痛 | 肺炎 |
护士 | 咽痛 | 感冒 |
下面来了一个咽痛的护士,我们要确定她患了什么疾病,这里就要用到贝叶斯定理。
该护士感冒的概率为:
P(感冒|护士,咽痛)=P(护士,咽痛|感冒)×P(感冒)P(咽痛,护士)=P(护士|感冒)×P(咽痛|感冒)×P(感冒)P(咽痛)×P(护士)=0.5×0.5×0.330.33×0.5=0.5
同理,该护士肺炎的概率为:
P(肺炎|护士,咽痛)=P(护士,咽痛|肺炎)×P(肺炎)P(咽痛,护士)=P(护士|肺炎)×P(咽痛|肺炎)×P(肺炎)P(咽痛)×P(护士)=0.33×0.33×0.50.33×0.5=0.33
该护士肺结核的概率为:
P(肺结核|护士,咽痛)=P(护士,咽痛|肺结核)×P(肺结核)P(咽痛,护士)=P(护士|肺结核)×P(咽痛|肺结核)×P(肺结核)P(咽痛)×P(护士)=1×0×1/60.33×0.5=0
所以,由上可知,咽痛的护士,最可能是感冒了。虽然上面的例子是瞎掰的,训练集数量太少,但是也能说明贝叶斯分类器的工作原理,即可能性最大的那个分类就作为输入特征向量的分类。
朴素(naive)贝叶斯有两个假设:
- 各个特征之间是相互独立的,即一个特征出现与否,不影响另一个特征是否出现。例如自然语言中 “ I am a student. ”,I 的出现肯定会影响 am 的出现,即主语的出现肯定会影响谓语的出现。但是朴素贝叶斯假设它们之间都没有联系,即在统计意义上是独立的。
- 各个特征同等重要,其实这个假设也有问题,在文档分类中,很多情况下,某些词比其他词更加重要。
虽然上面两个假设都不太符合实际,但是在实际情况中朴素贝叶斯分类器的效果却还是非常不错的,而且这两个假设使得程序代码逻辑清晰且简单。
(二)数据准备
由文本转化成数据向量,比如网站评论词,按照是否有侮辱性词语,转化为0、1为元素的向量,这里讲文本按照是否在已有词表中出现过标识为
0、1为元素的向量。词表是准备好的关注的词条。
#《机器学习实战》贝叶斯分类学习
from numpy import *
#构建数据样本和集合标签集
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']]
#标签 1 标识有侮辱性 0 否
classVec = [0,1,0,1,0,1]
return postingList,classVec
#数据集词条去重(利用set特性)
def createVocabList(dataSet):
#构建空集合
vocabSet = set([])
for document in dataSet:
#并集计算,将数据添加至vocabSet
vocabSet = vocabSet | set(document)
return list(vocabSet)
#将数据集转化为数据向量
#根据词条是否在词表中出现过转化为向量
def setOfWord2Vec(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
测试:
from ML_Learn.com.ML.Class.bayes import bayes
#数据准备-文本转向量测试
postingList,classVec = bayes.loadDataSet()
postingList.sort()
print(postingList)
vocabList = bayes.createVocabList(postingList)
vocabList.sort()
print("vocabList: ", vocabList)
print("postingList[0]: ", postingList[0])
returnVec = bayes.setOfWord2Vec(vocabList,postingList[0])
print(returnVec)
# [['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'], ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'], ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'], ['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid'], ['stop', 'posting', 'stupid', 'worthless', 'garbage']]
# vocabList: ['I', 'ate', 'buying', 'cute', 'dalmation', 'dog', 'flea', 'food', 'garbage', 'has', 'help', 'him', 'how', 'is', 'licks', 'love', 'maybe', 'mr', 'my', 'not', 'park', 'please', 'posting', 'problems', 'quit', 'so', 'steak', 'stop', 'stupid', 'take', 'to', 'worthless']
# postingList[0]: ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid']
# [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0]
(三)特征的贝叶斯概率计算
将输入特征如(x,y)写成向量w,公式变为:
#朴素贝叶斯分类器训练函数
#文档矩阵,每篇文档标签的向量[1,0,xxxxxxx]
def trainNB0(trainMatrix,trainCategory):
numTranDocs = len(trainMatrix)
numWords = len(trainMatrix[0])#总的词数目
#计算标签1出现的概率
pAbusive = sum(trainCategory)/float(numTranDocs)
p0Num = zeros(numWords)
p1Num = zeros(numWords)
p0Denom = 0.0; p1Denom = 0.0
#遍历所有文档
for i in range(numTranDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
p1Vect = p1Num/p1Denom
p0Vect = p0Num/p0Denom
return p0Vect,p1Vect,pAbusive
测试:
#朴素贝叶斯分类器训练函数
postingList,classVec = bayes.loadDataSet()
vocabList = bayes.createVocabList(postingList)
print("index of stupid: ",vocabList.index("stupid"))
trainMat = []
for postinDoc in postingList:
trainMat.append(bayes.setOfWord2Vec(vocabList,postinDoc))
p0V,p1V,pAb = bayes.trainNB0(trainMat,classVec)
print("pAb: ",pAb)
print("p0V: ",p0V)
print("p1V: ",p1V)
(四)贝叶斯函数计算
修改trainNB0
# 朴素贝叶斯分类器训练函数
# 文档矩阵,每篇文档标签的向量[1,0,xxxxxxx]
def trainNB0(trainMatrix, trainCategory):
numTranDocs = len(trainMatrix)
numWords = len(trainMatrix[0]) # 总的词数目
# 计算标签1出现的概率
pAbusive = sum(trainCategory) / float(numTranDocs)
# 解决个别为0的应用,初识化为1,分母初识化为2
# p0Num = zeros(numWords)
# p1Num = zeros(numWords)
# p0Denom = 0.0; p1Denom = 0.0
p0Num = ones(numWords)
p1Num = ones(numWords)
p0Denom = 2.0;p1Denom = 2.0
# 遍历所有文档
for i in range(numTranDocs):
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(p(w|c)p(c)) = log(p(w|c)) + log(p(c)),对于分类都除p(w),比较大小时可以略去
# 朴素贝叶斯分类函数
# log(p(w|c)p(c)) = log(p(w|c)) + log(p(c))
# 对于分类都除p(w),比较大小时可以略去
def classifyNB(vec2Classify, p0Vec, p1vec, pClass1):
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(setOfWord2Vec(myVocabList, postinDoc))
p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))
testEntry = ['love', 'my', 'dalmation']
thisDoc = array(setOfWord2Vec(myVocabList, testEntry))
print (testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
testEntry = ['stupid', 'garbage']
thisDoc = array(setOfWord2Vec(myVocabList, testEntry))
print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
#测试贝叶斯分类函数
bayes.testingNB()
# ['love', 'my', 'dalmation'] classified as: 0
# ['stupid', 'garbage'] classified as: 1