python实现贝叶斯推断的例子

目录
  • 1. 前言
  • 2. 问题描述
  • 3. 贝叶斯规则
  • 4. Bayes engine: scalar implementation
  • 5. Bayes engine: vectorization
  • 6. 测试
  • 7. 后记

1. 前言

本文介绍一个贝叶斯推断的python实现例,并展现了基于标量运算的实现和基于numpy的矩阵运算的实现之间的差别。

2. 问题描述

本问题例取自于Ref1-Chapter1.

问题描述:假设有一个制作灯泡的机器。你想知道机器是正常工作还是有问题。为了得到答案你可以测试每一个灯泡,但是灯泡数量很多,每一个都测试在实际生产过程中可能是无法承受的。使用贝叶斯推断,你可以基于少量样本(比如说抽检结果)来估计机器是否在正常地工作(in probabilistic way)。

构建贝叶斯推断时,首先需要两个要素:

(1) 先验分布

(2) 似然率

先验分布是我们关于机器工作状态的初始信念。首先我们确定第一个刻画机器工作状态的随机变量,记为M。这个随机变量有两个工作状态:{working, broken},以下简写成{w, br}(缩写成br是为了与下面的Bad缩写成b区分开来)。作为初始信念,我们相信机器是好的,是可以正常工作的,定义先验分布如下:

P(M=working) = 0.99

P(M=broken ) = 0.01

这表明我们对于机器正常工作的信念度很高,有99%的概率能够正常工作。

第二个随机变量是L,表示机器生产的灯泡的工作状态。灯泡可能是好,也可能是坏的,包含两个状态:{good, bad},以下简写成{g,b},注意br与b的区别。

我们需要基于机器工作状态给出L的先验分布,也就是条件概率P(L|M),在贝叶斯公式中它代表似然概率(likelihood)。

定义这个似然概率分布(由于M和L各有两种状态,所以一共包含4个条件概率)如下:

P(L=Good|M=w) = 0.99

P(L=Bad |M=w) = 0.01

P(L=Good|M=br ) = 0.6

P(L=Bad |M=br ) = 0.4

以上似然概率表明,在机器正常时我们相信每生成100个灯泡只会有一个坏的,而机器不正常时也不是所有灯泡都是坏的,而是有40%会是坏的。为了实现的方便,可以写成如下的矩阵形式:

现在,我们已经完整地刻画了贝叶斯模型,可以用它来做一些神奇的估计和预测的工作了。

我们的输入是一些灯泡的抽检结果。假设我们抽检了十个灯泡其抽检结果如下:

{bad, good, good, good, good, good, good, good, good, good}

让我们来看看基于贝叶斯推断的我们对于机器工作状态的信念(后验概率)如何变化。

3. 贝叶斯规则

贝叶斯推断规则以贝叶斯公式的形式表示为:

具体映射到本问题中可以表达如下:

         贝

叶斯推断的优先在于可以以在线(online)的方式进行,即观测数据可以一个一个地到来,每次受到一个新的观测数据,就进行一次基于贝叶斯公式的后验概率的计算更新,而更新后的后验概率又作为下一贝叶斯推断的先验概率使用。因此在线的贝叶斯推断的基本处理流程如下所示:

4. Bayes engine: scalar implementation

首先,我们以标量运算的方式写一个函数来进行bayes推断处理。

prior以向量的形式存储先验概率分布,prior[0]表示P(M=working),prior[1]表示P(M=broken)。

likelihood以矩阵的形式方式存储似然概率分布。其中第1行表示P(L/M=working),第2行表示P(L/M=broken).

在本例中,当输入 时,evidence的计算式(注意evidence是依赖于输入的观测数据的)是:

注意,当我写P(w)其实是表示P(M=w),而 其实是表示 ,余者类推。根据上下文,这些应该不会导致混淆。

第一个函数的代码如下:

def bayes_scalar(prior, likelihood, data):
    """
    Bayesian inference function example.
    Parameters
    ----------
    prior : float, 1-D vector
        prior information, P(X).
    likelihood : float 2-D matrix
        likelihood function, P(Y|X).
    data : List of strings. Value: 'Good','Bad'
        Observed data samples sequence
    Returns
    -------
    posterior : float
        P(X,Y), posterior sequence.
    """

    posterior = np.zeros((len(data)+1,2))
    posterior[0,:] = prior  # Not used in computation, just for the later plotting

    for k,L in enumerate(data):
        if L == 'good':
            L_value = 0
        else:
            L_value = 1
        #print(L, L_value, likelihood[:,L_value])

        evidence      = likelihood[0,L_value] * prior[0] + likelihood[1,L_value] * prior[1]
        LL0_prior_prod= likelihood[0,L_value] * prior[0]
        posterior[k+1,0]  = LL0_prior_prod / evidence

        LL1_prior_prod= likelihood[1,L_value] * prior[1]
        posterior[k+1,1]  = LL1_prior_prod / evidence

        prior = posterior[k+1,:] # Using the calculated posterior at this step as the prior for the next step

    return posterior

5. Bayes engine: vectorization

我们注意到,evidence的计算可以表示成两个向量的点积,如下所示。

这样就非常方便用numpy来实现了。本例中每个随机变量只有两种取值,在复杂的情况下,每个随机变量有很多种取值时,有效利用向量或矩阵的运算是简洁的运算实现的必不可缺的要素。以上这两个向量的点积可以用numpy.dot()来实现。

另外,likelihood和prior的乘积是分别针对M的两种状态进行计算(注意,我们需要针对M的两种不同状态分别计算posterior),不是用向量的点积进行计算,而是一种element-wise multiplication,可以用numpy.multiply()进行计算。所以在vectorization版本中贝叶斯更新处理削减为两条语句,与上面的scalar版本相比显得非常优雅简洁(好吧,也许这个简单例子中还显不出那么明显的优势,但是随着问题的复杂度的增加,这种优势就会越来越明显了。)

由此我们得到向量化处理的函数如下:

def bayes_vector(prior, likelihood, data):
    """
    Bayesian inference function example.
    Parameters
    ----------
    prior : float, 1-D vector
        prior information, P(X).
    likelihood : float 2-D matrix
        likelihood function, P(Y|X).
    data : List of strings. Value: 'Good','Bad'
        Observed data samples sequence
    Returns
    -------
    posterior : float
        P(X,Y), posterior sequence.
    """

    posterior = np.zeros((len(data)+1,2))
    posterior[0,:] = prior  # Not used in computation, just for the later plotting

    for k,L in enumerate(data):
        if L == 'good':
            L_value = 0
        else:
            L_value = 1
        #print(L, L_value, likelihood[:,L_value])

        evidence          = np.dot(likelihood[:,L_value], prior[:])
        posterior[k+1,:]  = np.multiply(likelihood[:,L_value],prior)/evidence

        prior = posterior[k+1,:] # Using the calculated posterior at this step as the prior for the next step

    return posterior

6. 测试

让我们来看看利用以上函数对我们的观测数据进行处理,后验概率将会如何变化。

import numpy as np
import matplotlib.pyplot as plt

prior      = np.array([0.99,0.01])
likelihood = np.array([[0.99,0.01],[0.6,0.4]])
data       = ['bad','good','good','good','good','good','good','good']        

posterior1 = bayes_scalar(prior,likelihood,data)
posterior2 = bayes_vector(prior,likelihood,data)

if np.allclose(posterior1,posterior2):
    print('posterior1 and posterior2 are identical!')

fig, ax = plt.subplots()
ax.plot(posterior1[:,0])
ax.plot(posterior1[:,1])
ax.grid()
# fig.suptitle('Poeterior curve vs observed data')
ax.set_title('Posterior curve vs observed data')
plt.show()

运行以上代码可以得到后验概率的变化如下图所示(注意第一个点是prior):

当然以上代码也顺便验证了一下两个版本的bayes函数是完全等价的。

7. 后记

大功告成。

第1个关于贝叶斯统计的学习的程序和第1篇关于贝叶斯统计的学习的博客。

其它有的没的等想到了什么再回头来写。

[Ref1] 《概率图模型:基于R语言》,David Bellot著, 魏博译

到此这篇关于python实现贝叶斯推断的例子的文章就介绍到这了,更多相关python 贝叶斯推断内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python实现朴素贝叶斯分类器的方法详解

    本文实例讲述了Python实现朴素贝叶斯分类器的方法.分享给大家供大家参考,具体如下: 贝叶斯定理 贝叶斯定理是通过对观测值概率分布的主观判断(即先验概率)进行修正的定理,在概率论中具有重要地位. 先验概率分布(边缘概率)是指基于主观判断而非样本分布的概率分布,后验概率(条件概率)是根据样本分布和未知参数的先验概率分布求得的条件概率分布. 贝叶斯公式: P(A∩B) = P(A)*P(B|A) = P(B)*P(A|B) 变形得: P(A|B)=P(B|A)*P(A)/P(B) 其中 P(A)是

  • python 机器学习之实现朴素贝叶斯算法的示例

    特点 这是分类算法贝叶斯算法的较为简单的一种,整个贝叶斯分类算法的核心就是在求解贝叶斯方程P(y|x)=[P(x|y)P(y)]/P(x) 而朴素贝叶斯算法就是在牺牲一定准确率的情况下强制特征x满足独立条件,求解P(x|y)就更为方便了 但基本上现实生活中,没有任何关系的两个特征几乎是不存在的,故朴素贝叶斯不适合那些关系密切的特征 from collections import defaultdict import numpy as np from sklearn.datasets import

  • Python实现朴素贝叶斯的学习与分类过程解析

    概念简介: 朴素贝叶斯基于贝叶斯定理,它假设输入随机变量的特征值是条件独立的,故称之为"朴素".简单介绍贝叶斯定理: 乍看起来似乎是要求一个概率,还要先得到额外三个概率,有用么?其实这个简单的公式非常贴切人类推理的逻辑,即通过可以观测的数据,推测不可观测的数据.举个例子,也许你在办公室内不知道外面天气是晴天雨天,但是你观测到有同事带了雨伞,那么可以推断外面八成在下雨. 若X 是要输入的随机变量,则Y 是要输出的目标类别.对X 进行分类,即使求的使P(Y|X) 最大的Y值.若X 为n 维

  • python实现基于朴素贝叶斯的垃圾分类算法

    一.模型方法 本工程采用的模型方法为朴素贝叶斯分类算法,它的核心算法思想基于概率论.我们称之为"朴素",是因为整个形式化过程只做最原始.最简单的假设.朴素贝叶斯是贝叶斯决策理论的一部分,所以讲述朴素贝叶斯之前有必要快速了解一下贝叶斯决策理论.假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示. 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中用圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中用三角形表示的类别)的概率,那么对于一个新数

  • 朴素贝叶斯分类算法原理与Python实现与使用方法案例

    本文实例讲述了朴素贝叶斯分类算法原理与Python实现与使用方法.分享给大家供大家参考,具体如下: 朴素贝叶斯分类算法 1.朴素贝叶斯分类算法原理 1.1.概述 贝叶斯分类算法是一大类分类算法的总称 贝叶斯分类算法以样本可能属于某类的概率来作为分类依据 朴素贝叶斯分类算法是贝叶斯分类算法中最简单的一种 注:朴素的意思是条件概率独立性 P(A|x1x2x3x4)=p(A|x1)*p(A|x2)p(A|x3)p(A|x4)则为条件概率独立 P(xy|z)=p(xyz)/p(z)=p(xz)/p(z)

  • python实现朴素贝叶斯分类器

    本文用的是sciki-learn库的iris数据集进行测试.用的模型也是最简单的,就是用贝叶斯定理P(A|B) = P(B|A)*P(A)/P(B),计算每个类别在样本中概率(代码中是pLabel变量) 以及每个类下每个特征的概率(代码中是pNum变量). 写得比较粗糙,对于某个类下没有此特征的情况采用p=1/样本数量. 有什么错误有人发现麻烦提出,谢谢. [python] view plain copy # -*- coding:utf-8 -*- from numpy import * fr

  • python实现朴素贝叶斯算法

    本代码实现了朴素贝叶斯分类器(假设了条件独立的版本),常用于垃圾邮件分类,进行了拉普拉斯平滑. 关于朴素贝叶斯算法原理可以参考博客中原理部分的博文. #!/usr/bin/python # -*- coding: utf-8 -*- from math import log from numpy import* import operator import matplotlib import matplotlib.pyplot as plt from os import listdir def

  • 朴素贝叶斯算法的python实现方法

    本文实例讲述了朴素贝叶斯算法的python实现方法.分享给大家供大家参考.具体实现方法如下: 朴素贝叶斯算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 比如我们想判断一个邮件是不是垃圾邮件,那么我们知道的是这个邮件中的词的分布,那么我们还要知道:垃圾邮件中某些词的出现是多少,就可以利用贝叶斯定理得到. 朴素贝叶斯分类器中的一个假设是:每个特征同等重要 函数 loadDataSet() 创建数据集,这里的数据集

  • 用Python从零实现贝叶斯分类器的机器学习的教程

    朴素贝叶斯算法简单高效,在处理分类问题上,是应该首先考虑的方法之一. 通过本教程,你将学到朴素贝叶斯算法的原理和Python版本的逐步实现. 更新:查看后续的关于朴素贝叶斯使用技巧的文章"Better Naive Bayes: 12 Tips To Get The Most From The Naive Bayes Algorithm" 朴素贝叶斯分类器,Matt Buck保留部分版权 关于朴素贝叶斯 朴素贝叶斯算法是一个直观的方法,使用每个属性归属于某个类的概率来做预测.你可以使用这

  • python机器学习之贝叶斯分类

    一.贝叶斯分类介绍 贝叶斯分类器是一个统计分类器.它们能够预测类别所属的概率,如:一个数据对象属于某个类别的概率.贝叶斯分类器是基于贝叶斯定理而构造出来的.对分类方法进行比较的有关研究结果表明:简单贝叶斯分类器(称为基本贝叶斯分类器)在分类性能上与决策树和神经网络都是可比的.在处理大规模数据库时,贝叶斯分类器已表现出较高的分类准确性和运算性能.基本贝叶斯分类器假设一个指定类别中各属性的取值是相互独立的.这一假设也被称为:类别条件独立,它可以帮助有效减少在构造贝叶斯分类器时所需要进行的计算. 二.

随机推荐