机器学习实战之朴素贝叶斯

本文详细介绍朴素贝叶斯算法的基本原理与应用实践,包括条件独立假设、贝叶斯估计及如何利用该算法进行垃圾邮件过滤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文为自己学习机器学习所记笔记,主要参考《统计学习方法》和《机器学习实战》两本书。朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设 的分类方法。

1.统计学基础

条件独立公式,如果X与Y相互独立

                                                   

条件概率公式:

                                                   

                                                   

可得概率交换公式: 

                                                         

全概率公式:

                                                          

带入得贝叶斯公式

                                                        

将Y换成类别,X为特征,那么贝叶斯公式可以理解为:已知特征的情况下,求属于某一类别的概率。

对于不同的种类,公式中的分母都是相同的,因此朴素贝叶斯分类器可以表示为:


即选择使得在特征x下,属于该类别概率最大的类别。因此我们要求的所属类别,需要计算 P(X=x|Y=ck)和P(Y=ck)

P(Y=ck)易求得,而贝叶斯分类器假设各个特征之间相互独立(这是其“朴素”的原因),因此有

                              

这样带入上述公式便可求出y。

2.朴素贝叶斯算法

输入:训练集,其中,为第i个样本的第j个特征,的可能取值为

输出:实例x的 分类

(1)计算先验概率及条件概率

                                           

(2)对于给定实例x,计算

                                         

(3)确定x的类

                                           

3.贝叶斯估计

用极大似然估计计算概率时可能会出现由于样本数据不够而导致要估计的概率为零的情况,这显然不合理,解决这一问题的办法是贝叶斯估计,计算条件概率的贝叶斯估计为:

                                      

其中Sj为X(j)可取值的数目,,等价于在随机变量各个取值的频数上赋予一个正数时就是极大似然估计,通常取,这是称为拉普拉斯平滑。

计算先验概率的贝叶斯估计为

                                               

4 实例 用朴素贝叶斯过滤垃圾邮件,参考《机器学习实战》

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']]
    classVec = [0, 1, 0, 1, 0, 1]  # 1 is abusive, 0 not
    return postingList, classVec
#创建一个包含所有文档中出现的不重复的词汇列表
def creatVocabList(dataSet):
    vocabSet=set()
    for document in dataSet:
        vocabSet=vocabSet|set(document)
    return list(vocabSet)
#输入参数为某个文档的词汇表和待查找词汇表,输出为文档向量,向量的每一元素为0或1,表示词汇表中的单词在文档中是否出现。
def setOfWords2List(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 vocabList!'% word)
    return returnVec
#计算在给定文档类别条件下词汇表中单词出现的概率,输入为文档向量矩阵,元素为0和1,类别向量
#输出为不同类别条件下单词出现概率向量
def trainNB0(trainMatrix,labelVec):
    numTraindocs=len(trainMatrix)
    numWords=len(trainMatrix[0])
    pAbusive=sum(labelVec)/float(numTraindocs)
    p0num=ones(numWords)
    p1num=ones(numWords)
    p0Denom=2.0
    p1Denom=2.0
    for i in range(numTraindocs):
        if labelVec[i] == 1:
            p1num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect =log(p1num/p1Denom)          #change to log()
    p0Vect =log(p0num/p0Denom)          #change to log()
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2classify,p0v,p1v,pclass1):
    p1=sum(vec2classify*p1v)+log(pclass1)
    p0=sum(vec2classify*p0v)+log(1-pclass1)
    if p1>p0:
        return 1
    else:
        return 0
#词袋向量,可以统计重复出现的词
def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

def testingNB():
    PostList, classVec = loadDataSet()
    print('PostList=', PostList)
    vocabList = creatVocabList(PostList)
    print('vocabList=', vocabList)
    trainMat = []
    for postinDoc in PostList:
        trainMat.append(setOfWords2List(vocabList, postinDoc))
    print('trainMat=', trainMat)
    p0v, p1v, pab = trainNB0(trainMat, classVec)
    print(p0v, '\n', p1v, '\n', pab)
    testEntry=['love','my','dagouzi']
    thisDoc=array(setOfWords2List(vocabList,testEntry))
    print(testEntry,'classified as :',classifyNB(thisDoc,p0v,p1v,pab))
    testEntry=['stupid','garbage']
    thisDoc = array(setOfWords2List(vocabList, testEntry))
    print(testEntry, 'classified as :', classifyNB(thisDoc, p0v, p1v, pab))
#输入为长string,输出为词汇列表
def textParse(bigstring):
    import re
    listOfTokens=re.split(r'\W*',bigstring)
    return [tok.lower() for tok in listOfTokens if len(tok)>2]

def spamTest():
    docList=[];  classList=[];  fullText=[]
    for i in range(1,26):
        wordList=textParse(open('D:\python\code\machinelearninginaction\Ch04\email\spam\%d.txt' % i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
        wordList=textParse(open('D:\python\code\machinelearninginaction\Ch04\email\ham\%d.txt' % i,encoding='gb18030',errors='ignore').read())
        #此处若无‘encoding='gb18030',errors='ignore'’,则会出现编码错误,详见https://blog.youkuaiyun.com/shijing_0214/article/details/51971734
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
    vocabList=creatVocabList(docList)

    trainingSet=list(range(50)); testSet=[]
    for i in range(20):
        randIndex=int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])

    trainMat=[]; trainClass=[]
    for docIndex in trainingSet:
        trainMat.append(bagOfWords2VecMN(vocabList,docList[docIndex]))
        trainClass.append(classList[docIndex])

    p0v,p1v,pspam=trainNB0(array(trainMat),array(trainClass))

    errorCount=0
    for docIndex in testSet:
        wordVec=bagOfWords2VecMN(vocabList,docList[docIndex])
        if classifyNB(wordVec,p0v,p1v,pspam)!=classList[docIndex]:
            errorCount+=1
            print('classification error:',docList[docIndex])
    print('Error rate is:',float(errorCount)/len(testSet))




#testingNB()
spamTest()




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值