7、贝叶斯算法Bayes

本文详细介绍了贝叶斯算法在垃圾邮件处理中的应用,包括原理、流程图以及具体实现步骤,如数据准备、训练与测试过程,重点展示了朴素贝叶斯分类器如何通过计算单词概率来进行邮件分类。
摘要由CSDN通过智能技术生成

原理

举例:

1、出处:

正常思路:一个不透明的盒子中,黑球N个,白球M个==>取到黑球的概率,取到白球的概率
逆向思路:已知取到黑球的概率、白球的概率==>白球的个数,黑球的个数
2、推导公式:
学校的人数U,男生穿长裤,女生穿长裤或裙子==>穿长裤的女生的概率
P(Boy),P(Girl),P(Pants),P(Dress)是可以直接得到的
P(Girl|Pants)=P(Pants,Girl)/P(Pants)=P(Pants|Girl)P(Girl)/P(Pants)
P(Pants)=P(Boy)P(Pants|Boy)+P(Girl)P(Pants|Girl)
3、当所求的条件概率较难时,转换成条件概率
P(A|B)=P(AB)/P(B)=P(B|A)P(A)/P(B)

垃圾邮件处理:

1、宏观
下面的算法介绍,共有50篇邮件,25篇垃圾邮件,25篇正常邮件,有监督分类:
分类40篇训练数据,10篇测试
2、微观
D:表示一篇邮件,由N个单词组成,h+表示垃圾邮件,h-表示正常邮件
P(h+|D),P(h-|D)对比大小,判断时正常还是垃圾
P(h+|D)=P(D|h+)P(h+)/P(D)
P(D|h+)=P(d1,d2,…,dN|h+)链式求解
=P(d1|h+)P(d2|d1,h+)…P(dN|d1,d2,…,dN-1,h+)
朴素贝叶斯算法:每一个词都是独立存在,相互之间时没有关系的
所以可以化简为
=P(d1|h+)P(d2|h+)…P(dN|h+)

算法

1、流程图

在这里插入图片描述

2、基础准备:

1、主程序:

def spam():
    #1、进行数据读取
    doclist=[]#存放数据
    classlist=[]#存放标签
    error=[]#存放预测错误的列表

    for i in range(1,26):#每个都有26个邮件
        wordlist=textParse(open('email/spam/%d.txt' % i,'r').read())#将读取的数据分割
        doclist.append(wordlist)
        classlist.append(1)#1表示垃圾邮件

        wordlist = textParse(open('email/ham/%d.txt' % i, 'r').read())
        doclist.append(wordlist)
        classlist.append(0)  # 0表示正常邮件

    #2、创建语料表,统计一下出现的词总共有哪些
    vocablist=creatVocablist(doclist)
    
    trainSet=list(range(50))#先将所有都作为训练集合
    testSet=[]#测试列表初始化

#随机挑选10个测试数据,作为测试数据,从训练集中剔除
    for i in range(10):#当前个数

        randIndex=int(random.uniform(0,len(trainSet)))
        testSet.append(trainSet[randIndex])#训练集中剔除的数据作为测试集
        del (trainSet[randIndex])#将随机选择的值,从训练集中剔除

    #3、进行训练啦
    trainMat=[]#训练矩阵
    trainClass=[]#训练标签
    
    #将当前的一句话转换成向量
    #1、训练模块只计算概率值
    #2、转化成向量,当作一个函数书写
    for docIndex in trainSet:
        #进行向量填充
        trainMat.append(setOfWord2Vec(vocablist,doclist[docIndex]))#将训练的数据转成向量存储
        #list标为1,
        trainClass.append(classlist[docIndex])#训练的标签

    p0Vec,p1Vec,p1=trainNB(np.array(trainMat),np.array(trainClass))


    #测试数据
    errorCount=0#统计错误的数量
    for docIndex in testSet:
        wordVec=setOfWord2Vec(vocablist,doclist[docIndex])
        if classifyNB(np.array(wordVec),p0Vec,p1Vec,p1)!=classlist[docIndex]:#预测与标签对比
            errorCount+=1
            error.append(docIndex)
    print('当前10个测试样本,错了:', errorCount)
    print("testSet:",testSet)
    print('error:',error)

2、分解单词

用正则表达式

def textParse(input_string):
    listofToken=re.split(r'\W+',input_string)#将所有字符进行切分
    return [tok.lower() for tok in listofToken if len(listofToken)>2]#将字符转换成小写

3、创建语料库

def creatVocablist(doclist):
    vocabSet=set([])#每个词都是不重复的,直接用集合

    for document in doclist:
        vocabSet=vocabSet | set(document)#将两者取成一个

    return list(vocabSet)

4、将文章转换成向量存储:

def setOfWord2Vec(vocablist, inputSet):
#直接创建语料库大小的列表,出现的单词置为1
    returnVec=[0]*len(vocablist)#保证每一遍做出了的向量都是相同的,用语料表的大小来表示
    for word in inputSet:#[0]*len(vocabList)列表*一个常数,则列表扩宽原来的常数被,内部的值重复
        if word in vocablist:
            returnVec[vocablist.index(word)]=1
    # 若单词出现在语料库,就将单词设置为1
    return returnVec

5、训练数据:

分别计算正常和垃圾,语料库中的单词所出现的概率

# p0Vec,p1Vec,p1=trainNB(np.array(trainMat),np.array(trainClass))调用方式和返回值表示
def trainNB(trainMat, trainClass):

    numTrainDocs=len(trainMat)#训练的矩阵的长度40
    numWords=len(trainMat[0])#是语料库的大小
    #trainMat=40*769

#p1是垃圾邮件,标注为1的
    p1=sum(trainClass)/float(numTrainDocs)#训练集中的垃圾邮件所占的比例P(h+)
    # p0=1-p1#训练集中正常邮件所占概率P(h-)

#为什么要为1?因为一旦出现某一个单词是0,那么概率相乘直接为0
    p0Num=np.ones((numWords))#平滑处理,不能为0,创建语料库大小的769
    p1Num=np.ones((numWords))#拉普拉斯平滑

    p0Denom=2#通常设置为类别的个数
    p1Denom=2
    
    for i in range(numTrainDocs):#总共40个
    
        if trainClass[i]==1:#为垃圾的时候
            p1Num+=trainMat[i]
            p1Denom+=sum(trainMat[i])

        else:

            p0Num+=trainMat[i]
            p0Denom+=sum(trainMat[i])
	#为什么为log?因为连乘转换成log就是连加,且概率都是小于1的数,连乘太小
    p1Vec=np.log(p1Num/p1Denom)#得到的概率很小,相乘几乎为0
    #不需要确切的值 ,只需要相对的大小值,取对数进行了放大
    p0Vec=np.log(p0Num/p0Denom)

    return p0Vec,p1Vec,p1

6、测试数据

def classifyNB(wordVec, p0Vec, p1Vec, p1_class):
    # 转换成log,所有相加就可以,测试的文章的向量wordvec与
    p1 = np.log(p1_class) + sum(wordVec * p1Vec)#垃圾邮件各个单词所占的概率

    p0=np.log(1.0-p1_class)+sum(wordVec*p0Vec)#正常邮件各个单词所占的概率
    if p0>p1:
        return 0
    else:
        return 1
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值