贝叶斯分类器浅讲

故事起因,在一个很有意思的up主下面随意留的言,发现有很多朋友给我点赞哈哈,顺便就在暑假忙里偷闲浅浅翻了概率论的书复习下录个视频讲下~大家开心就好
在这里插入图片描述

贝叶斯分类器教学

1:在概率和统计学领域,贝叶斯理论基于对某一事件证据的认识来预测该事件的发生概率,2:在机器学习领域,贝叶斯分类器是基于贝叶斯理论并假设各特征相互独立的分类方
3:贝叶斯分类器就是条件概率:给定一个实体,求解这个实体属于某一类的概率。

作用:分类+概率,能够很明显地想到分类器的作用就是用来分类
(听君一席话胜读十年书)

举例,下面是不同水果的不同属性(属性理解为颜色、添堵、数量等等),贝叶斯分类器可以实现,你输入一些属性,不告诉他是什么水果(可以黑色的盒子装起来),分类器会基于下面表的属性,去预测黑色盒子里面的到底是什么水果

视频地址B站讲解 比较浅
-----------本期视频到这里就结束了!谢谢大家观看---------------

文章参考
https://blog.csdn.net/qq_25948717/article/details/81744277

下面是详细介绍!!!!(高能预警) 数学推导 + 代码
|
|
|
|
|
|
|
|

预备知识:

条件概率: P(A|B)=P(AB)/P(B)
左边=事件A在事件B发生的情况下发生的概率
右边=事件AB共同发生的概率 ÷ 事件B发生的概率

举例,事件A=我发视频 事件B=你们点赞

P(A|B) 可以理解为,如果你们给我点赞(事件B发生),那么之后我发视频(事件A发生)的概率

P(AB)也就是 你们给我点赞,并且我发视频的概率

P(B) 就是你们点赞的概率

如果单纯不考虑数学逻辑推理,凭借经验,是不是可以得出,你们点赞越多,up主发视频的概率越多?
——>在等式中,这个正比例也是成立的。
比如,P(AB)越大,假设P(B)越小 那么P(A|B)越大

贝叶斯定理:

这个是 贝叶斯定理
在这里插入图片描述
“进化版后的”贝叶斯公式,不做要求
在这里插入图片描述
条件概率理解了,这个也就很好理解吧,有什么不一样?
等式右边的分子发生了变动!
之前是P(AB),变成了P(B|A)P(A)
文字理解为:
你们给我点赞(事件B发生),并且我发视频(事件A发生)的概率

等于

我发视频和你们给我点赞同时发生的概率 等于 我发视频后你们再给我点赞的概率× 我发视频的概率

现在就大概了解了 贝叶斯定理的基本公式什么意思了,以及他的增长情况。

预备知识最后一步
先验概率: 指根据以往经验和分析。在实验或采样前就可以得到的概率。
后验概率:指某件事已经发生,想要计算这件事发生的原因是由某个因素引起的概率。

p(瓜熟):是先验概率。作为“因”,瓜熟有自己的固有概率,这就叫“先验”
p(瓜熟|蒂落):是后验概率。当观察到了“果”然后推算“因”的条件概率

似然概率:就是说我们现在有一堆数据,现在需要构建一组参数对这些数据建模,以使得模型能够尽可能地拟合这些数据。所以我们要做的就是从很多组参数中选出一组使得模型对数据的拟合程度最高,所以也常常说最大似然概率

比如,x,y 第一象限有很多点(离散点,彼此独立),对模型,通俗来说叫y=kx函数进行建模,k就是我们需要构建的参数,使得这些点尽量分布or靠近去y=kx模型的附近
在这里插入图片描述
模型大概如下,尽可能让点分布两侧即可
在这里插入图片描述
k的取值有很多很多,从中选出比较优秀的k值 的概率,就是常说的最大似然概率

准备工作到此结束

假设我们有一个手写的数据集样本mnist,里面有100条记录,记录1-10是10个人各自写的0,记录11-20是10个人各自写的1,………以此类推一共100条记录。那么这时候外头有个人进来写了个数字X,怎么识别出来它写的几呢?没学习过机器学习的人可能也能提出这样一种方法:我们只要把写的那个数字和0-9进行匹配,那个匹配度最高就是哪个数啦。没错,朴素贝叶斯用的就是这样朴素的思想(开玩笑,这里的朴素可不是这个意思)。

朴素贝叶斯工作原理:假设Y表示是数字几,写的那个数叫X,那么我们可以通过某种方法求P(Y = 1 | X),P(Y = 1 | X),…….,P(Y = 9| X)。其中P(Y = 1 | X)表示在给定手写数字X的情况下,它是1的概率。这样得出10个数字各自的概率,哪个高就最有可能是哪个。那么咋求这个P(Y = 1 | X)

总之,朴素贝叶斯分类器就是一个对所有可能性求概率的模型,最后输出结果中哪种可能性高就输出哪种。核心公式是P(Y | X),至于P(Y | X) = ?,这部分怎么求?我们现在开始用数学的知识开始讨论。
在这里插入图片描述
数学公式看不懂就看不懂吧,起码得知道其计算过程!
(1)首先根据给定的训练样本求先验概率和条件概率,也就是上文求的那两个式子
(2)然后训练计数后给定一个样本,
(3)计算在不同类别下该样本出现的概率,求得最大值即可。

接下来看代码!

基于给定的mnist手写数字集,训练先验概率分布和条件概率分布并返回

def getAllProbability(trainDataArr, trainLabelArr):
    '''
    通过训练集计算先验概率分布和条件概率分布
    :param trainDataArr: 训练数据集
    :param trainLabelArr: 训练标记集
    :return: 先验概率分布和条件概率分布
    '''
    #设置样本特诊数目,数据集中手写图片为28*28,转换为向量是784维。
    # (我们的数据集已经从图像转换成784维的形式了,CSV格式内就是)
    featureNum = 784
    #设置类别数目,0-9共十个类别
    classNum = 10
    #初始化先验概率分布存放数组,后续计算得到的P(Y = 0)放在Py[0]中,以此类推
    #数据长度为10行1列
    Py = np.zeros((classNum, 1))
    #对每个类别进行一次循环,分别计算它们的先验概率分布
    #计算公式为书中"4.2节 朴素贝叶斯法的参数估计 公式4.8"
    for i in range(classNum):
        #下方式子拆开分析
        #np.mat(trainLabelArr) == i:将标签转换为矩阵形式,里面的每一位与i比较,若相等,该位变为Ture,反之False
        #np.sum(np.mat(trainLabelArr) == i):计算上一步得到的矩阵中Ture的个数,进行求和(直观上就是找所有label中有多少个
        #为i的标记,求得4.8式P(Y = Ck)中的分子)
        #np.sum(np.mat(trainLabelArr) == i)) + 1:参考“4.2.3节 贝叶斯估计”,例如若数据集总不存在y=1的标记,也就是说
        #手写数据集中没有1这张图,那么如果不加1,由于没有y=1,所以分子就会变成0,那么在最后求后验概率时这一项就变成了0,再
        #和条件概率乘,结果同样为0,不允许存在这种情况,所以分子加1,分母加上K(K为标签可取的值数量,这里有10个数,取值为10)
        #参考公式4.11
        #(len(trainLabelArr) + 10):      标签集的总长度+10.
        #((np.sum(np.mat(trainLabelArr) == i)) + 1) / (len(trainLabelArr) + 10):最后求得的先验概率
        Py[i] = ((np.sum(np.mat(trainLabelArr) == i)) + 1) / (len(trainLabelArr) + 10)
    #转换为log对数形式
    #log书中没有写到,但是实际中需要考虑到,原因是这样:
    #最后求后验概率估计的时候,形式是各项的相乘(“4.1 朴素贝叶斯法的学习” 式4.7),这里存在两个问题:1.某一项为0时,结果为0.
    #这个问题通过分子和分母加上一个相应的数可以排除,前面已经做好了处理。2.如果特诊特别多(例如在这里,需要连乘的项目有784个特征
    #加一个先验概率分布一共795项相乘,所有数都是0-1之间,结果一定是一个很小的接近0的数。)理论上可以通过结果的大小值判断, 但在
    #程序运行中很可能会向下溢出无法比较,因为值太小了。所以人为把值进行log处理。log在定义域内是一个递增函数,也就是说log(x)中,
    #x越大,log也就越大,单调性和原数据保持一致。所以加上log对结果没有影响。此外连乘项通过log以后,可以变成各项累加,简化了计算。
    #在似然函数中通常会使用log的方式进行处理
    Py = np.log(Py)
    #计算条件概率 Px_y=P(X=x|Y = y)
    #计算条件概率分成了两个步骤,下方第一个大for循环用于累加,参考书中“4.2.3 贝叶斯估计 式4.10”,下方第一个大for循环内部是
    #用于计算式4.10的分子,至于分子的+1以及分母的计算在下方第二个大For内
    #初始化为全0矩阵,用于存放所有情况下的条件概率
    Px_y = np.zeros((classNum, featureNum, 2))
    #对标记集进行遍历
    for i in range(len(trainLabelArr)):
        #获取当前循环所使用的标记
        label = trainLabelArr[i]
        #获取当前要处理的样本
        x = trainDataArr[i]
        #对该样本的每一维特诊进行遍历
        for j in range(featureNum):
            #在矩阵中对应位置加1
            #这里还没有计算条件概率,先把所有数累加,全加完以后,在后续步骤中再求对应的条件概率
            Px_y[label][j][x[j]] += 1
    #第二个大for,计算式4.10的分母,以及分子和分母之间的除法
    #循环每一个标记(共10个)
    for label in range(classNum):
        #循环每一个标记对应的每一个特征
        for j in range(featureNum):
            #获取y=label,第j个特诊为0的个数
            Px_y0 = Px_y[label][j][0]
            #获取y=label,第j个特诊为1的个数
            Px_y1 = Px_y[label][j][1]
            #对式4.10的分子和分母进行相除,再除之前依据贝叶斯估计,分母需要加上2(为每个特征可取值个数)
            #分别计算对于y= label,x第j个特征为0和1的条件概率分布
            Px_y[label][j][0] = np.log((Px_y0 + 1) / (Px_y0 + Px_y1 + 2))
            Px_y[label][j][1] = np.log((Px_y1 + 1) / (Px_y0 + Px_y1 + 2))
    #返回先验概率分布和条件概率分布
    return Py, Px_y

NaiveBayes函数 基于输入的先验概率分布,先验概率分布以及样本x
输出所有label的估计概率

def NaiveBayes(Py, Px_y, x):
    '''
    通过朴素贝叶斯进行概率估计
    :param Py: 先验概率分布
    :param Px_y: 条件概率分布
    :param x: 要估计的样本x
    :return: 返回所有label的估计概率
    '''
    #设置特征数目
    featrueNum = 784
    #设置类别数目 0-9
    classNum = 10
    #建立存放所有标记的估计概率数组
    P = [0] * classNum
    #对于每一个类别,单独估计其概率
    for i in range(classNum):
        #初始化sum为0,sum为求和项。
        #在训练过程中对概率进行了log处理,所以这里原先应当是连乘所有概率,最后比较哪个概率最大
        #但是当使用log处理时,连乘变成了累加,所以使用sum
        sum = 0
        #获取每一个条件概率值,进行累加
        for j in range(featrueNum):
            sum += Px_y[i][j][x[j]]
        #最后再和先验概率相加(也就是式4.7中的先验概率乘以后头那些东西,乘法因为log全变成了加法)
        P[i] = sum + Py[i]
    #max(P):找到概率最大值
    #P.index(max(P)):找到该概率最大值对应的所有(索引值和标签值相等)
    return P.index(max(P))

最后不忘老本行,公众号AI知识物语 如果有帮助到你的,可以关注我呀!

代码是参考一位大佬的,在这里致谢 respect! 写得很用心
代码链接
详细数学公式讲解看这里

猜你喜欢

转载自blog.csdn.net/qq_40514113/article/details/131625317
今日推荐