#encoding:utf8
import numpy as np
import cmath
import math
"""
贝叶斯决策理论的核心思想,就是选择最高概率的决策
使用贝叶斯准则可以交换条件概率中的条件与结果P(x|c) = P(c|x)*P(x)/P(c)
"""
"""
条件概率公式
贝叶斯推断是贝叶斯定理的用应,而贝叶斯定理实则是计算条件概率的公式
所谓条件概率就是指在事件B发生的情况下,事件A发生的概率,用P(A|B)来表示
根据文氏图
P(A|B) = P(A∩B) / P(B)
P(A∩B) = P(A|B) * P(B)
P(B∩A) = P(B|A) * P(A)
P(A|B) * P(B) = P(B|A) * P(A)
P(A|B) = P(B|A) * P(A) / P(B)
"""
"""
全概率公式
样本空间S,是两个事件A和A`的和。在这种情况下事件B可以分为两部分
如果A和A`构成样本空间的一个划分,那么事件B的概率,就等于A和A`的概率分别乘以B对这两个事件的条件概率之和
P(B) = P(B∩A) + P(B∩A`)
P(B∩A) = P(B|A) * P(A)
P(B) = P(B|A) * P(A) + P(B|A`) * P(A`)
"""
"""
贝叶斯推断的含义
对条件概率公式进行变形,可以得到如下形式
P(A|B) = P(A) *[P(B|A)/P(B)]
我们可以把P(A)称为"先验概率",既在事件B发生之前,我们对A事件概率的一个判断。P(A|B)称为“后验概率”,既在B事件发生后对A概率的重新估计,
P(B|A)/P(B)称为“可能性函数”,这是一个调整因子,使得预估概率更接近真实概率。既
后验概率 = 先验概率 * 调整因子
这就是贝叶斯推断的含义。我们先预估一个“先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了“先验概率”,由此得到更接近事实的“后验概率”
如果"可能性函数"P(B|A)/P(B)>1,意味着"先验概率"被增强,事件A的发生的可能性变大;如果"可能性函数"=1,意味着B事件无助于判断事件A的可能性;
如果"可能性函数"<1,意味着"先验概率"被削弱,事件A的可能性变小。
"""
"""
朴素贝叶斯
优点:在数据较少的情况下仍然有效,可以处理多类别问题
缺点:对于输入的数据的准备方式较为敏感
适用数据类型:标称型数据
"""
"""
朴素贝叶斯的一般过程
(1)收集数据:可以使用任何方法,rss源
(2)准备数据:需要数值型或者布尔型数据
(3)分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好
(4)训练算法:计算不同的独立特征的条件概率
(5)测试算法:计算错误率
(6)使用算法:一个常见的朴素贝叶斯应用就是文本档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本
"""
#此朴素贝叶斯分类器是基于伯努利模型实现的
#定义一个词表到向量的转换函数
def loadDataSet():
postingList = [['我的','狗','有','跳蚤','问题','帮助','请'],
['可能','不','拿','他的','到','狗','公园','愚蠢'],
['我的','达尔宁','是','那么','可爱的','我','爱','他的'],
['停','邮寄','愚蠢','无价值','垃圾'],
['先生','舔','吃','我的','牛排','如何','到','停','他'],
['戒烟','买','无价值','狗','食物','愚蠢']]
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):
print(inputSet)
returnVec = [0]*len(vocablist)#创建一个其中所含元素都为0的向量
for word in inputSet:#遍历文档中所有的单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1
if word in vocablist:
returnVec[vocablist.index(word)] = 1
else:
print("the word: %s is not in my Vocabulary" %(word))
return returnVec
'''
我们将每个词的出现与否作为一个特征这可以被描述为词集模型。
如果一个词在文档中出现不止一次,这可能意味着该词在文档中的意义超过这个词本身的意义。
这种方法被称为词袋模型
在词袋中,每个单词可以出现多次,而在词集中,每个词出现一次
为了适用词袋模型,需要对函数setOfWords2Vec稍加修改,修改后的函数叫bagOfWords2VecMN
'''
def bagOfWords2VecMN(vocabList, inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
#训练算法(计算每个类别的条件概率,伪代码)
'''
计算每个类别中的文档数目
对每篇训练文档:
对每个类别:
如果次条出现在文档中-->增加该词条的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目除以总词条的数目得到条件概率
返回每个类别的条件概率
'''
def trainNB0(trainMatrix, trainCategory):
'''
朴素贝叶斯分类器训练函数(此处仅处理两分类问题)
trainMatrix:文档矩阵
trainCategory:每篇文档类别标签
'''
numTrainDocs = len(trainMatrix)
print(numTrainDocs)
numWords = len(trainMatrix[0])
print(numWords)
pAbusive = sum(trainCategory)/float(numTrainDocs)
print(pAbusive)
#初始化所有词出现数为1,并将分母初始化为2,避免某一个概率值为0
p0Num = np.ones(numWords)
print(p0Num)
p1Num = np.ones(numWords)
print(p1Num)
p0Denom = 2.0
p1Denom = 2.0
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
# print(p1Num)
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
# print(p0Num)
p0Denom += sum(trainMatrix[i])
#将结果取自然对数,避免下溢出,即太多很小的数相乘造成的影响
p1Vect = [math.log(x/p1Denom) for x in p1Num]#得到每一个侮辱性词汇出现的概率
p0Vect = [math.log(y/p0Denom) for y in p0Num]#得到每一个正常词汇出现的概率
print(p1Vect)
print(p0Vect)
return p0Vect, p1Vect, pAbusive
#分类函数
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
'''
分类函数
:param vec2Classify:要分类的向量
:param p0Vec: 分别对应trainNB0计算得到的3个概率
:param p1Vec:
:param pClass1:
:return:
'''
p1 = sum(vec2Classify * p1Vec) + cmath.log(pClass1)
p0 = sum(vec2Classify * p0Vec) + cmath.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(setOfWords2Vec(myVocabList, postinDoc))#将训练数据整理成标准样式
print(trainMat)
#训练模型,注意此处使用array
p0V, p1V, pAb = trainNB0(np.array(trainMat), np.array(listClasses))
testEntry = ['爱','我的','达尔宁']
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
print(thisDoc)
print(testEntry,'classified as: ',classifyNB(thisDoc, p0V, p1V, pAb))
testEntry = ['愚蠢', '垃圾','爱','问题','狗','先生','舔','吃','我的','牛排','如何','到','停','他']
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
if __name__ == '__main__':
# listOPosts, listClasses = loadDataSet()
# vocabSet = createVocabList(listOPosts)
# print('11111',listOPosts[0])
# returnVec = setOfWords2Vec(vocabSet, listOPosts[0])
# print(returnVec)
testingNB()
结合朴素贝叶斯实现的文本相似度算法https://github.com/zhao-dapeng/Cosine觉得有用的朋友记得star
个人搭建的肿瘤社区http://www.h2cancer.com/希望能为肿瘤患者提供一个交流互助的平台