朴素贝叶斯算法(Naïve Bayes)

目录

一、朴素贝叶斯算法概述

二、朴素贝叶斯算法原理

1. 贝叶斯定理

(1)条件概率

(2)联合概率

(3)贝叶斯公式

(4)全概率公式

2. 朴素贝叶斯公式

三、代码

1. 数据集

2. 代码实现:

1、创建词汇表

2、建立词袋、词集模型

3、贝叶斯公式

4、分类文档

5、所有单词转化为小写

6、测试分类器

7、调用进行实验

四、总结


一、朴素贝叶斯算法概述

朴素贝叶斯(Naïve Bayes, NB)算法,是一种基于贝叶斯定理与特征条件独立假设的分类方法。朴素:特征条件独立;贝叶斯:基于贝叶斯定理。

属于监督学习的生成模型,实现简单,并有坚实的数学理论(即贝叶斯定理)作为支撑。在大量样本下会有较好的表现,不适用于输入向量的特征条件有关联的场景。

二、朴素贝叶斯算法原理

1. 贝叶斯定理

定义

贝叶斯理论是以18世纪的一位神学家托马斯.贝叶斯(Thomas Bayes)命名。通常,事件A在事件B(发生)的条件下的概率,与事件B在事件A(发生)的条件下的概率是不一样的。然而,这两者是有确定的关系的,贝叶斯定理就是这种关系的陈述。

(1)条件概率

定义

就是事件 A 在另外一个事件 B 已经发生条件下的发生概率。条件概率表示为P(A|B),读作“在 B 发生的条件下 A 发生的概率”。

条件概率公式

设A,B是两个事件,且P(B)>0,则在事件B发生的条件下,事件A发生的条件概率为:

P(A|B)=P(AB)/P(B)

(2)联合概率

定义

表示两个事件共同发生(数学概念上的交集)的概率。A 与 B 的联合概率表示为联合概率。

联合概率公式

由条件概率公式得出乘法公式:

 P(AB)=P(A|B)P(B)=P(B|A)P(A)

(3)贝叶斯公式

P(A|B) = P(AB)/P(B)可变形为:

即为贝叶斯公式。

先验概率——即P(A),在B事件发生前根据以往经验就可求得的A概率,如收到一封邮件,是垃圾邮件。

后验概率——即P(A|B),在B发生后对A发生概率进行的重新评估,如收到一封邮件,如果含有某个词这个邮件是垃圾邮件。

(4)全概率公式

即:

2. 朴素贝叶斯公式

朴素贝叶斯方法是基于贝叶斯定理和特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布;然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。

朴素贝叶斯贝叶斯不同的点为——朴素贝叶斯采用了属性条件独立性假设,即每个属性对结果产生独立的影响。

公式
   令 x 表示训练集 X 中可能的类别数,表示第i个属性可能的取值数,则贝叶斯公式可修正为

因为可能有数据收集不全可能的情况即有的数据为0导致直接为另一个结果,所以可以利用拉普拉斯修正,公式为:

Ni为第i个属性可能的取值数

因为所有结果值都为小数所以可能在最后累乘时产生下溢出情况,所以可采用对数化:

防止下溢出。

三、代码

1. 数据集

本次实验中,所采用的数据集来源:

垃圾邮件数据集

数据集分为spam(垃圾)和ham(正常)

spam邮件:

ham邮件:

2. 代码实现:

1、创建词汇表

#创建词汇表
def createwordList(dataSet):
    #dataSet:包含多个文档的数据集
    vocabSet = set([])#去重词汇表
    for document in dataSet:
        vocabSet=vocabSet|set(document)#取并集
    return list(vocabSet)

2、建立词袋、词集模型

词集模型单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个

词袋模型:在词集的基础上如果一个单词在文档中出现不止一次,统计其出现的次数(频数)。

不同词袋词集有没有某词的基础上更关注有几个某词。

#词集模型
def setOfWords(vocabList,inputSet):
    #vocabList:去重词汇表
    #inputSet:输入文档
    returnVec=[0]*len(vocabList)  #建立和去重词汇表相同长度的全0向量
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]=1  #遍历所有单词,如果存在使相应向量=1
        else:print("妹这个单词哦~")
    return returnVec
 
#词袋模型
def bagOfWords(vocabList,inputSet):
    returnVec=[0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)]+=1
    return returnVec

3、贝叶斯公式

#训练朴素贝叶斯
def trainBYS(trainMatrix,trainClasses):
    #trainMatrix:每个returnVec组成的矩阵
    #trainClasses:每个reVec对应的类别,1侮辱类 0正常类
 
    numTrainDocs=len(trainMatrix) #总文档数
    numWords=len(trainMatrix[0]) #每个文档总字数
    p_1=sum(trainClasses)/float(numTrainDocs) #文档属于侮辱类
    #拉普拉斯修正_防止下溢出
    p0Num=np.ones(numWords)  #分子各单词出现数初始化为1
    p1Num=np.ones(numWords) 
    p0Denom=2.0  #分母总单词数初始化为类别数 2
    p1Denom=2.0
    
    for i in range(numTrainDocs):  #遍历训练样本
        if trainClasses[i]==1:
            p1Num+=trainMatrix[i]  #侮辱类各个单词数量
            p1Denom+=sum(trainMatrix[i])  #侮辱类总单词数量
        else:
            p0Num+=trainMatrix[i]
            p0Denom+=sum(trainMatrix[i])
 
    p1Vect=np.log(p1Num/p1Denom)  #取对数
    p0Vect=np.log(p0Num/p0Denom) 
    #print(p0Vect)
    return p0Vect,p1Vect,p_1

4、分类文档

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    '''
    对测试文档进行分类
    
    Parameter:
    vec2Classify:测试文档向量
    p0Vec:正常类中每一个词的条件概率
    p1Vec:侮辱类中每一个词的条件概率
    pClass1:侮辱类占总样本概率
    '''
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)    	
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else: 
        return 0

5、所有单词转化为小写

#将字符串转换为小写字符列表
def textParse(bigString):   
    '''
    Parameter:
    bigString:输入字符串
    
    Return:
    tok.lower():小写字符列表
    '''       
                                             
    #将特殊符号作为切分标志进行字符串切分,即非字母、非数字
    listOfTokens = re.split(r'\W+', bigString)
    #除了单个字母,其它单词变成小写                   
    return [tok.lower() for tok in listOfTokens if len(tok) > 2] 

6、测试分类器

#测试朴素bys分类器
def spamTest(method='bag'):
    #method有bag词袋和set词集两中
    
    if method == 'bag':                   #判断使用词袋模型还是词集模型
        words2Vec = bagOfWords
    elif method == 'set':
        words2Vec = setOfWords
    
    docList=[]
    classList=[]
 
    #遍历文件夹
    for i in range(1,26):
        #读取垃圾邮件 转化乘字符串列表
        wordList=textParse(open('C:/Users/kid/Desktop/ML/machine-learning-master/Naive Bayes/email/spam/%d.txt' % i,'r').read())
        #将列表记录加入文档列表并分类为1 侮辱类
        docList.append(wordList)
        classList.append(1)
        #读取正常文件
        wordList=textParse(open('C:/Users/kid/Desktop/ML/machine-learning-master/Naive Bayes/email/ham/%d.txt' % i,'r').read())
        docList.append(wordList)
        classList.append(0)
 
 
    #创建去重词汇表
    vocabList=createwordList(docList)
    #print(vocabList)
 
    #创建索引
    trainSet=list(range(50))
    testSet=[]
 
    #分割测试急
    for i in range(10):
        #从索引中随机抽取十个并从索引中删除十个
        randIndex=int(random.uniform(0,len(trainSet)))
        testSet.append(trainSet[randIndex])
        del(trainSet[randIndex])
 
    #创建训练集矩阵和类别向量
    trainMat=[]
    trainClasses=[]
 
    for docIndex in trainSet:
        #将生成模型添加到训练矩阵并记录类别
        trainMat.append(words2Vec(vocabList,docList[docIndex]))
        trainClasses.append(classList[docIndex])
 
    #训练bys
    p0V,p1V,pSpam=trainBYS(np.array(trainMat),np.array(trainClasses))
 
    #错误分类器
    error=0
 
    for docIndex in testSet:
        wordVec=words2Vec(vocabList,docList[docIndex])
        #测试
        if classifyNB(np.array(wordVec),p0V,p1V,pSpam)!=classList[docIndex]:
            error+=1
            #print("分类错误的:",docList[docIndex])
    #print("错误率:%.2f%%"%(float(error)/len(testSet)*100))
    errorRate=float(error)/len(testSet)#分类错误率
    return errorRate

7、调用进行实验

 
if __name__ == "__main__":
    total = 100
    print('使用词袋模型训练:')
    sum_bag_error = 0
    for i in range(total):
        sum_bag_error += spamTest(method = 'bag')
    print('使用词袋模型训练' + str(total) + '次得到的平均错误率为: ' + str((sum_bag_error / total)))

结果为:

四、总结

朴素贝叶斯优缺点:
优点:在数据较少的情况下仍然有效,可以处理多类别问题
缺点:对于输入数据的准备方式较为敏感,由于朴素贝叶斯的“特征条件独立”特点,所以会带来一些准确率上的损失
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值