《机器学习实战》学习笔记-[4]-基于概率的分类-朴素贝叶斯

本文介绍了朴素贝叶斯算法的基本概念、原理及其在文本分类中的应用。通过具体实例展示了如何构建贝叶斯分类器,并提供了详细的代码实现,包括数据准备、特征选择、概率计算及分类预测等关键步骤。

朴素贝叶斯算法

(一)基本概念

贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。

这个定理解决了现实生活里经常遇到的问题:已知某条件概率,如何得到两个事件交换后的概率,也就是在已知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

源代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值