首页 > 其他分享 >Chapter4 朴素贝叶斯

Chapter4 朴素贝叶斯

时间:2023-04-22 12:56:37浏览次数:40  
标签:概率 词条 Chapter4 贝叶斯 文档 条件 类别 朴素

朴素贝叶斯


1. 简介

    朴素贝叶斯是一种基于概率论的分类方法。它主要借助条件概率和贝叶斯公式来对样本进行分类。

2. 优缺点

    朴素贝叶斯优点:在数据较少的情况下仍然有效,可以处理多类别问题。
    缺点:对于输入数据的准备方式较为敏感。
    适用数据类型:标称型数据。

3. 条件概率与贝叶斯公式

    在介绍朴素贝叶斯之前,我们需要了解一下条件概率与贝叶斯公式。先看下面的案例:

img

    根据古典概型:
    灰色石头的概率:3/7
    黑色石头的概率:4/7
    再看一组案例:

img

    那么,我们需要计算两个问题:
        1. A桶中,灰球的概率是多少?
        2. B桶中,灰球的概率是多少?
    根据上图,我们不难得到:
        1. 2/4
        2. 1/3
    因此,上述两个问题的概率就是条件概率。用公式表示:
        1. P(gray|bucketA)
        2. P(gray|bucketB)
    接下来,我们给出条件概率的计算公式: 

img

    我们来验证一下上述公式:
        根据上图,我们可以知道P(gray and bucketB)的结果为1/7,P(bucketB)的结果为3/7,因此上述公式的概率为1/3,跟上述结果是相等的。
    接下来,我们计算一下这个概率:
        已知一个球是灰球,求其在B桶的概率,即P(bucketB|gray)。
        上述的这个条件概率就是贝叶斯公式。因此,贝叶斯公式是另外一种计算条件概率的方法。将上面的条件概率进行展开:
        P(bucketB|gray) = P(gray and bucketB) / P(gray)
        最后计算的结果是1/3。
如果已知P(x|c),想求P(c|x),那么可以采用下面的计算方法(贝叶斯公式)

img

4. 使用条件概率与贝叶斯公式来进行分类

    我们先给出需要进行分类的贝叶斯公式:

img

    其中上述公式的i代表类别数
    使用上述两个公式进行分类的准则如下:

    给定两个条件概率:P(c1|x,y)和P(c2|x,y),现在需要判断点(x,y)属于哪个类别。
        If P(c1|x,y) > P(c2|x,y),则(x,y)点属于类别c1
        If P(c1|x,y) < P(c2|x,y),则(x,y)点属于类别c2
    相信你看到这里,肯定是满头雾水。别着急,我们将上述的公式抽象成实际问题。
    假设,我们有一组训练样本(特征和类别已知)和测试样本(特征已知,类别未知)。样本的类别为ci。样本的特征有两种,均为x和y,我们可以抽象成点(x,y)。
    那么,通过训练样本,对于以下三种概率,我们肯定是已知的。
        1. 点(x,y)的概率,即特征取值分别为x和y的概率
        2. ci的概率,即类别ci在训练样本中的概率
        3. 在类别为ci的条件下,特征取值为x和y的概率。即条件概率P(x,y|ci)。
    由于在测试样本中,类别是未知的。我们需要通过某一个点来反推该点属于某一类别的概率。即,特征取值为x和y,该点(x,y)属于某个类别的概率?即P(ci|x,y)。
    因此,这就是为什么要采用贝叶斯公式来进行样本分类。

4. 朴素贝叶斯的一般过程

    朴素贝叶斯的一般过程
    (1)收集数据:可以使用任何方法。本章使用RSS源。
    (2)准备数据:需要数值型或者布尔型数据。
    (3)分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
    (4)训练算法:计算不同的独立特征的条件概率。
    (5)测试算法:计算错误率。
    (6)使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。

5. 使用Python来进行文本分类

    在使用条件概率和贝叶斯公式以及进行文本分类之前,我们需要进行数据的预处理操作。即,从文本当中如何获取特征?
    要想从文本中获取特征,首先需要拆分文本。这里的特征是来自于文本的词条。词条可以是一个单词也可以是非单词(URL、IP地址等)将文本拆分为一个个的词条之后,再将该文本转换为词条向量,其中值为1代表词条出现在该文档中,值为0代表没有出现在该文档中。(我们根据什么将文本转换为对应的词条向量?往后看)
    接下来,我们以一段文本是否为侮辱性和非侮辱性言论进行分类为例。其中,该文本为侮辱性言论为1,否则为0。
    在将一段文本转换为词条向量之前,我们需要去获取所有文本中所出现的词条列表,在根据这个词条列表将一段文本转换为对应的词条向量。
# 该函数的作用是加载数据集(训练集)
# 具体就是划分为一个个词条的文档和这个文档所对应的分类
# 该函数位于bayes.py文件中

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']]
    # 代表每个文档所对应的分类(0代表正常言论,1代表侮辱性言论)
    classVec = [0,1,0,1,0,1]

    return postingList,classVec
# 该函数的作用就是根据输入的训练集(文档集合),生成所有文档中所出现的词条列表
# 之后可根据该词条列表来构建出每一个文档所对应的词条向量,进而利用朴素贝叶斯来计算条件概率
# 该函数位于bayes.py文件中

def createVocabList(dataSet):
    # 创建集合的目的就是所输入的文档集合不可避免的会出现一些重复的词条,因此我们需要进行去重。
    vocabSet = set()                # 创建一个空集合,代表词条列表
    for document in dataSet:
        vocabSet = vocabSet | set(document)         # 将文档中出现的词条去重之后,添加到词条列表中。 | 代表求并集
    return list(vocabSet)           # 返回词条列表,以列表的形式
# 该函数的作用就是根据词条列表来返回每一个文档所对应的词条向量
# 函数的两个参数分别为:词条列表、输入文档(划分完词条后)
# 该函数位于bayes.py文件中

def setOfWords2Vec(vocabList,inputSet):
    returnVec = [0]*len(vocabList)          # 生成该文档的词条向量,该词条向量的长度与词条列表相同。并初始化为0
                                            # 其中词条向量中的某个词条为0代表该词条未出现在该词条列表中,如果出现则为1
    for word in inputSet:                   # 遍历每一个词条
        if word in vocabList:               # 如果该词条出现在了词条列表中,
            returnVec[vocabList.index(word)] = 1    # 则词条向量中的对应词条置为1
        else:
            print("the word %s is not in my Vocabulary" % word)     # 输出
    return returnVec                        # 返回该文档所对应的词条向量
# 该函数的作用是用于测试
# 该函数位于personalTest.py文件中

import baye1

listOPosts,listClasses = baye1.loadDataSet()    # 加载训练集
myVocabList = baye1.createVocabList(listOPosts) # 生成词条列表
print(myVocabList)
'''
['stupid', 'buying', 'not', 'help', 'flea', 'please', 'ate', 
'licks', 'so', 'food', 'love', 'to', 'has', 'cute', 'mr',
 'is', 'posting', 'maybe', 'dalmation', 'park', 'how', 
 'problems', 'him', 'garbage', 'worthless', 'stop', 
 'steak', 'I', 'my', 'take', 'quit', 'dog']
'''
# 注意: 词条向量里面的每一个词条都是该文档(样本)的特征
# 只不过这里的特征只用0和1表示(0代表未出现,1代表出现)
print(baye1.setOfWords2Vec(myVocabList,listOPosts[0]))          # 输出第一个文档所对应的词条向量
'''
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0]

'''
print(baye1.setOfWords2Vec(myVocabList,listOPosts[3]))          # 输出第四个文档所对应的词条向量
'''
[0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
'''
    获取到了每个文档的词条向量之后,我们接下来需要利用它来计算条件概率。

6. 训练算法:从词条向量计算概率

    由于本案例当中特征数量很多,因此可将上述的贝叶斯公式更改一下,我们将使用更改完之后的贝叶斯公式来进行分类。(其中w代表测试样本的词条向量)

img

# 该函数的作用就是用于计算某个类别的概率以及以该类别为条件下每个特征(词条)的条件概率
# 注意:这里使用词条是否出现来当作特征,一个词条出现与否,与另一个词条出现与否无关,因此特征之间是相互独立的
# 因此P(w0,w1,...,wn|ci) = P(w0|ci)P(w1|ci)...P(wn|ci)
# 所以,该函数依照上述的条件概率公式来进行计算
# 该函数位于bayes.py文件中

# trainMatrix代表训练矩阵(里面存储的是每个文档所对应的词条向量)
# trainCategory存储的是每个文档所对应的类别
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)             # 训练文档的总数量
    numWords = len(trainMatrix[0])              # 词条数量(特征数量)(单词数量)
    # 这里需要注意:sum(trainCategory)代表文档属于侮辱性文档的数量
    # 由于本案例属于二类分类问题(侮辱性文档/非侮辱性文档),因此侮辱性文档与非侮辱性文档之间是相互对立的。
    # 因此非侮辱性文档的概率 = 1 - 侮辱性文档的概率
    pAbusive = sum(trainCategory) / float(numTrainDocs)     # 计算文档属于侮辱性文档的概率
    p0Num = zeros(numWords)                     # 代表记录属于类别0的每个单词出现数量的数组(初始化为0)
    p1Num = zeros(numWords)                     # 代表记录属于类别1的每个单词出现数量的数组(初始化为0)
    p0Denom = 0.0                               # 代表属于类别0的单词总数量
    p1Denom = 0.0                               # 代表属于类别1的单词总数量
    # 如何计算在某类别条件下某特征的概率?
    # P(wi|ci) = 某类别条件下该特征的总数量/某类别条件下的单词总数量
    for i in range(numTrainDocs):               # 遍历每一个文档(样本)
        if trainCategory[i] == 1:               # 如果该样本属于侮辱性文档
            p1Num += trainMatrix[i]             # 统计在侮辱性文档的前提下各个单词的出现次数
            p1Denom += sum(trainMatrix[i])      # 统计在侮辱性文档的前提下单词的总数量
        else:                                   # 非侮辱性
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    # 以下语句用于计算条件概率
    p1Vect = p1Num / p1Denom                    # p1Vect代表在类别1条件下各个特征的条件概率
    p0Vect = p0Num / p0Denom                    # 类别0
    return p0Vect,p1Vect,pAbusive
# 该函数的作用是用于测试
# 该函数位于personalTest.py文件中

import baye1

listOPosts,listClasses = baye1.loadDataSet()
myVocabList = baye1.createVocabList(listOPosts)
print(myVocabList)

trainMat = []

for postinDoc in listOPosts:
    trainMat.append(baye1.setOfWords2Vec(myVocabList,postinDoc))

p0V,p1V,pAb = baye1.trainNB0(trainMat,listClasses)

print(p0V)              # 类别0条件下各个特征的条件概率
print(p1V)              # 类别1
print(pAb)              # 文档为侮辱性文档的概率

'''
['my', 'park', 'take', 'mr', 'stupid', 'to', 'not', 'steak', 'is', 'how', 'I', 'ate', 'help', 'dog', 'worthless', 'stop', 'has', 'maybe', 'garbage', 'dalmation', 'food', 'posting', 'love', 'licks', 'quit', 'flea', 'cute', 'him', 'please', 'so', 'problems', 'buying']
[0.125      0.         0.         0.04166667 0.         0.04166667
 0.         0.04166667 0.04166667 0.04166667 0.04166667 0.04166667
 0.04166667 0.04166667 0.         0.04166667 0.04166667 0.
 0.         0.04166667 0.         0.         0.04166667 0.04166667
 0.         0.04166667 0.04166667 0.08333333 0.04166667 0.04166667
 0.04166667 0.        ]
[0.         0.05263158 0.05263158 0.         0.15789474 0.05263158
 0.05263158 0.         0.         0.         0.         0.
 0.         0.10526316 0.10526316 0.05263158 0.         0.05263158
 0.05263158 0.         0.05263158 0.05263158 0.         0.
 0.05263158 0.         0.         0.05263158 0.         0.
 0.         0.05263158]
0.5

'''
'''
    通过观察发现,类别1当中的第5个单词的条件概率最大,经查看单词列表发现这个单词为stupid,因此该单词是侮辱性文档中最具有代表性的单词。
'''

7. 测试算法:根据现实情况来修改分类器

    首先,上述算法会出现两个问题:
        1. 在条件概率相乘的过程,如果某个条件概率为0,那么总体概率就为0。这显然是不合理的。
        2. 每个条件概率都是不大于1的小数,当条件概率相乘时可能会出现下溢出,进而导致计算的结果不正确。
    因此,所提出的两个解决办法就是:
        1. 将某个类别条件下每个词的出现次数初始化为1,将某个类别条件下所有词的出现总数初始化为2。
        2. 为了避免下溢出问题,我们可以将计算的概率取自然对数。这里需要引进一个公式:ln(ab) = lna + lnb
    所以,我们需要将trainNB0这个函数进行一下修改。
p0Num = ones(numWords)                     # 代表记录属于类别0的每个单词出现数量的数组(初始化为0)
p1Num = ones(numWords)                     # 代表记录属于类别1的每个单词出现数量的数组(初始化为0)
p0Denom = 2.0                               # 代表属于类别0的单词总数量
p1Denom = 2.0                               # 代表属于类别1的单词总数量


p1Vect = log(p1Num / p1Denom)                    # p1Vect代表在类别1条件下各个特征的条件概率
p0Vect = log(p0Num / p0Denom)                    # 类别0
    解决了以上问题之后,我们就可以编写朴素贝叶斯的分类函数了。
# 该函数的作用是利用贝叶斯公式来进行分类
# 该函数有四个参数,第一个代表测试样本的词条向量,我们可以根据该向量
# 以及之后的p0Vec和p1Vec来获得在某些类别下该测试样本中每个特征的条件概率
# p0Vec代表在类别为0条件下,每个特征的条件概率
# p1Vec代表在类别为1条件下,每个特征的条件概率
# pClass1代表类别为1的概率
# 该函数使用了上述的贝叶斯公式来进行分类
# 该函数位于bayes.py文件中
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    # 计算在类别为1的条件下,通过贝叶斯公式计算的条件概率
    # 这里需要注意的是,p1Vec中的条件概率已经取了自然对数,每个独立特征的条件概率相乘取自然对数本质上就是自然对数相加的过程
    # ln(ab) = lna + lnb
    # 根据上述的贝叶斯公式,这里为什么没有除以测试样本特征的概率即p(w)?
    # 因为该测试样本只有一个,因此该测试样本特征的概率为1。
    p1 = sum(vec2Classify*p1Vec) + log(pClass1)
    # 计算在类别为0的条件下,通过贝叶斯公式计算的条件概率
    p0 = sum(vec2Classify*p0Vec) + log(1-pClass1)
    if(p1 > p0):                # 如果该测试样本属于类别1的概率大于类别0
        return 1                # 将该样本预测为类别1
    else:
        return 0                # 类别0
# 该函数的作用是用于测试朴素贝叶斯算法
# 该函数位于bayes.py文件中

def testingNB():
    listOPosts,listClasses = loadDataSet()      # 加载数据集
    myVocabList = createVocabList(listOPosts)   # 得到词条列表
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))  # 得到每个样本的词条向量,并添加到矩阵中
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))  # 得到三个概率
    testEntry = ['love','my','dalmation']                       # 测试样本
    thisDoc  = array(setOfWords2Vec(myVocabList,testEntry))     # 得到该测试样本的词条向量
    print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb)) # 对该测试样本进行分类
    testEntry = ['stupid','garbage']
    thisDoc = array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb))
# 该函数的作用是用于测试
# 该函数位于personalTest.py文件中

import baye1

baye1.testingNB()

'''
['love', 'my', 'dalmation'] classified as: 0
['stupid', 'garbage'] classified as: 1
'''
    最后需要补充的一点就是:上述案例将每个词的出现与否作为特征,这可以描述为词集模型。如果将每个词的出现次数作为特征,这就称为是词袋模型。

标签:概率,词条,Chapter4,贝叶斯,文档,条件,类别,朴素
From: https://www.cnblogs.com/gao79135/p/17342797.html

相关文章

  • PYTHON银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机SV
    全文下载链接:http://tecdat.cn/?p=26219最近我们被客户要求撰写关于银行机器学习的研究报告,包括一些图形和统计输出。该数据与银行机构的直接营销活动相关,营销活动基于电话。通常,需要与同一客户的多个联系人联系,以便访问产品(银行定期存款)是否会(“是”)或不会(“否”)订阅银行数据集我......
  • Chapter4 图例
    Chapter4图例图例的作用就是对所绘制的图像,进行解释。importmatplotlib.pyplotaspltimportnumpyasnpx=np.linspace(-3,3,50)y1=2*x+1y2=x**2plt.figure()#设置x轴的取值范围plt.xlim((-1,2))#设置y轴的取值范围plt.ylim((-2,3))#描述x轴plt......
  • Java语言在Spark3.2.4集群中使用Spark MLlib库完成朴素贝叶斯分类器
    一、贝叶斯定理贝叶斯定理是关于随机事件A和B的条件概率,生活中,我们可能很容易知道P(A|B),但是我需要求解P(B|A),学习了贝叶斯定理,就可以解决这类问题,计算公式如下:  P(A)是A的先验概率P(B)是B的先验概率P(A|B)是A的后验概率(已经知道B发生过了)P(B|A)是B的后验概率(已经知道A发生过了)二......
  • 决策论——贝叶斯决策的R实现(二)
    决策是理性人普遍从事的一种活动,也是极为重要的制胜手段。它的核心是,对未来活动的多个目标及用途做出合理的选择,以寻求最满意的行动方案。决策具有以下特点:①面对新问题和新任务做出科学决定,属于创造性的管理活动;②必须对实际行为有直接的指导作用;③具有多因素、多目标、不要确定......
  • python机器学习案例系列教程——文档分类器,朴素贝叶斯分类器,费舍尔分类器
    全栈工程师开发手册(作者:栾鹏)python数据挖掘系列教程github地址:https://github.com/626626cdllp/data-mining/tree/master/Bayes贝叶斯分类过程概述:首先有一批已知分类的数据集。对每个输入对象提取特征,根据输入对象的特征属性和输入对象的所属分类,计算分类与特征属性之间的概率......
  • 基于贝叶斯判决的手写数字识别系统,带GUI界面
    1.算法描述贝叶斯判别规则是把某特征矢量(x)落入某类集群的条件概率当成分类判别函数(概率判别函数),x落入某集群的条件概率最大的类为X的类别,这种判决规则就是贝叶斯判别规则。贝叶斯判别规则是以错分概率或风险最小为准则的判别规则。判别函数,各个类别的判别区域确定后,可以用......
  • 基于贝叶斯判决的手写数字识别系统,带GUI界面
    1.算法描述      贝叶斯判别规则是把某特征矢量(x)落入某类集群的条件概率当成分类判别函数(概率判别函数),x落入某集群的条件概率最大的类为X的类别,这种判决规则就是贝叶斯判别规则。贝叶斯判别规则是以错分概率或风险最小为准则的判别规则。       判别函数,各个......
  • 频率学派和贝叶斯学派
    贝叶斯定理贝叶斯推断是一种统计学方法,用来估计统计量的某种性质。贝叶斯推断与传统的频率学派不同,它是建立在主观判断的基础上的,也就是说,你可以不需要客观证据,先估计一个值,然后根据实际结果不断修正。由于其主观性太强,所以在一些传统行业内更偏向于传统的频率学派。贝叶斯定理......
  • 太赞了!机器学习基础核心算法:贝叶斯分类!(附西瓜书案例及代码实现)
     Datawhale 作者:尹晓丹,Datawhale优秀学习者寄语:首先,简单介绍了生成模型和判别模型,对条件概率、先验概率和后验概率进行了总结;其次,对朴素贝叶斯的原理及公式推导做了详细解读;再次,对三种可能遇到的问题进行了解析,给出了合理的解决办法;最后,对朴素贝叶斯的sklearn参数和代码进行了详......
  • 数据分享|R语言逻辑回归、Naive Bayes贝叶斯、决策树、随机森林算法预测心脏病|附代码
    全文链接:http://tecdat.cn/?p=23061最近我们被客户要求撰写关于预测心脏病的研究报告,包括一些图形和统计输出。这个数据集可以追溯到1988年,由四个数据库组成。克利夫兰、匈牙利、瑞士和长滩。"目标"字段是指病人是否有心脏病。它的数值为整数,0=无病,1=有病数据集信息:目标:主......