朴素贝叶斯分类器

#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/希望能为肿瘤患者提供一个交流互助的平台

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值