关于算法:PYTHON贝叶斯推断计算用BETA先验分布推断概率和可视化案例

5次阅读

共计 6852 个字符,预计需要花费 18 分钟才能阅读完成。

原文链接:http://tecdat.cn/?p=24084 

在这篇文章中,我将扩大从数据推断概率的示例,思考 0 和 1 之间的所有(间断)值,而不是思考一组离散的候选概率。这意味着咱们的先验(和后验)当初是一个 probability density function (pdf) 而不是 probability mass function (pmf)。

我思考了从数据序列推断 p0,即零的概率:

_我_应用 p0 的不同先验来_解决雷同的问题,该_先验容许 0 和 1 之间的间断值而不是一组离散的候选值。

概率

咱们推理问题的终点是 _似然_ ——察看到的数据序列的概率,写成就像我晓得 p0 的值一样:

 

为了分明起见,咱们能够插入 p0=0.6,并找到给定未知概率值的指定数据序列的概率:

可能性的更个别模式,不是特定于所思考的数据序列,是

其中 n0 是零的数量,n1 是思考的任何数据序列 D 中的 1 的数量。

先验 – Beta 散布

咱们应用贝塔散布来示意咱们的先验假如 / 信息。其数学模式是

其中 α0 和 α1 是咱们必须设置的超参数,反映咱们对于 p0 值的假如 / 信息。然而,只需将 p0 视为咱们想要推断的参数——疏忽参数是概率。

请留神 后验 pdf 也将是 Beta Distribution,因而值得致力适应 pdf。

先验均值—— 大多数人想要一个数字或点估计来示意推理后果或先验中蕴含的信息。然而,在贝叶斯推理方法中,先验和后验都是 pdf 或 pmf。取得点估计的一种办法是取 相干参数绝对于先验或后验的 _平均值_。例如,对于 Beta 先验咱们失去:

pdf 被归一化—— 这意味着如果咱们将 p0 从 0 积分到 1,咱们会失去一个:

因为以下关系:

就咱们而言,最重要的信息是 b 在 0 到 1 区间上进行归一化,这对于像 p0 这样的概率是必要的。

先验假如和信息能够通过设置超参数来反映 – 超参数 α0α0 和 α1α1 影响 pdf 的形态,使先验信息的编码更加灵便。

例如,应用 α0=1, α1=1 不能反映 p0 的优选值。这个 pdf 看起来像

另一个先验能够指定 α0=5, α1=5,它更靠近 p0=1/2 左近的值

最初,咱们能够用 α0≠α1 失去非对称的先验,能够看到 α0=2,α1=8。

 

对于设置超参数须要记住的一些事件:

  • 如果 α0=α1,先验将是对称的,先验平均值等于 Eprior[p0]=1/2。
  • 如果 α0≠α1,则先验将是不对称的,先验平均值不同于 1/21/2。
  • 先验的强度与 α0+α1 的总和无关。将 α 总和与数据中的 n0+n1 进行比拟,将 α 的视为假数。这些和的绝对大小管制着先验和似然对后验形态的影响。这在上面的 Python 例子中会变得很分明。

累积散布函数 (cdf)  beta累积散布函数 (cdf)让咱们计算 p0 小于或等于值 x 的概率。具体来说,cdf 定义为:

该积分也被称为不齐全 Beta ing 积分,并示意为 Ix(α0,α1)。

如果咱们想晓得 p0 在数值 xl 和 xh 之间的概率,咱们能够用 cdf 来计算。
 

不齐全 Beta 积分或 cdf 及其逆积分容许从先验或后验计算置信区间。应用这些工具,能够说 p0 的值有 95% 的概率在某个范畴内——同样,咱们将应用 Python 代码在上面绘制它。

贝塔散布是这个问题的共轭先验 – 这意味着后验将具备与先验雷同的数学模式(它也是一个贝塔散布),并更新了超参数。这种数学上的 “ 共鸣 “ 真的很好,让咱们不必 MCMC 就能做残缺的贝叶斯推断。

当初咱们谈谈贝叶斯定理和这个问题的后验 pdf。

贝叶斯定理和后验

咱们的最终目标是后验概率密度函数,联合似然和先验,在思考数据后对咱们对 p0 的常识做一个更新的反映。后验 pdf 的模式是(在这种状况下)。

换句话说,这是 _给定数据_序列 D _和先验假如的_ p0 _的概率密度__,由具备超参数_ (α0,α1)_的 Beta pdf 反映_。

在这种状况下,贝叶斯定理采纳以下模式:

其中后验 P(p0|D,α0,α1) 为蓝色,似然 P(D|p0)为彩色,先验 P(p0| α0,α1)是红色的。请留神,归一化 _边际似然_(上述等式中的分母)当初是一个积分。

尝试将贝叶斯定理视为对于 p0 从 假如  (α0,α1) 更新到  假如 + 数据 (D,α0,α1) 的信息:

试着把贝叶斯定理看作是对于 p0 的信息被从假如(α0,α1)更新为假如 + 数据(D,α0,α1)。

为了失去后验 pdf,咱们必须在贝叶斯定理的分母上做积分。在这种状况下,利用贝塔散布的个性,就能够进行计算。该积分如下。

最初一行的积分定义了一个贝塔函数,在对于先验的一节中探讨过,并且有一个已知的后果。
 

这意味着分母,也叫边际 似然,等于。

同样,咱们失去这个后果是因为 Beta 散布是咱们所思考的伯努利过程可能性的共轭先验。请留神,来自先验的超参数曾经被计数数据所更新。

这与人们预期的齐全一样,不须要做所有的数学计算。在任何状况下,在用 Python 实现这一点之前,有几个注意事项。
 

  • 后验 pdf 在 0 到 1 的区间内被归一化,就像咱们推断 p0 这样的概率时须要的那样。
  • 后验平均数,是对咱们的推断给出一个点估计的办法是

  • 后验的 cdf 和先验的一样,因为咱们依然有一个 Beta 散布 – 只不过,当初的参数是用数据更新的。在任何状况下,咱们都能够用不残缺的 Beta 积分和它的逆向找到置信区间,如上所述。

Python 中的推理代码

首先,咱们导入一些包,应用这些包来计算和绘制先验、似然和后验。此外,应用 matplotlib,在本例中为 ggplot,创立丑陋的图。

概率

    def _int(sef, daa):
        ""二进制数据的概率。""
        elfus = {s:0 for s in \['0', '1'\]}

    def proes_data(sef, ata):
        ""解决数据。""
        for s in \['0', '1'\]:
           unts\[s\] =cont(s)


        ""解决概率。""
        n0 = couts\['0'\]
        n1 = couts\['1'\]

        if p0 != 0 and p0 != 1:
            # 典型状况
            lgpdaa = n0*log(p0) + \
                         n1*log(1.-p0)
            rdta = exp(lgpata)
        elif p0 == 0 and n0 != 0:
            # 如果 n0 不是 0,p0 就不可能是 0
            lpr_dta = -np.inf
            p_dta = exp(lgrata)
        elif p0 == 0 and n0 == 0:
            # 数据与 p0= 0 统一
            lgpr_at = n1*np.log(1.-p0)
            p\_ata =.exp(lo\_dta)
        elif p0 == 1 and n1 != 0:
            # 如果 n1 不是 0,p0 就不可能是 1
            lpdta = -inf
            praa = exp(lor_ta)
        elif p0 == 1 and n1 == 0:
            # 数据与 p0= 1 统一
            log_dta = n0*log(p0)


    def prob(sef, p0):
        ""获取数据的概率。"""
        prdat,_ = .\_procs\_proabiti(p0)


    def logprob(sef, p0):
        ""获取数据的概率对数。"""
        _, lgpr\_a = sel\_presplies(p0)

先验散布

咱们的先验类基本上是一个围绕 scipy 的包,有一个绘图办法。留神 plot() 办法失去了 Beta 散布的平均值,并应用  interval() 办法失去了一个概率为 95% 的区域 – 这是应用不残缺的 Beta 积分和下面探讨的它的逆值实现的。
 

    def \_int\_(sef, alpa0=1, alph1=1):
        ""二进制数据的 β 先验。""

        elfa0 = alha0
        sl.1 = alha1
        slf.0r = ba(self.0, sef.a1)

    def intrval(slf, pb):
        ""蕴含 `prob' 的 pdf 区域的端点。例如:interval(0.95)
        """

        return sef.pvitervl(rob)

    def mean(self):
        """返回先验平均数。"""


    def pdf(self, p0):
        """p0 处的概率密度。"""

        return self.p.pdf(p0)

    def plot(self):
        ""显示平均值和 95% 置信区间的图。""

        fig, ax = tsuplots(1, 1)
        x = np.rae(0., 1., 0.01)

        # 取得先验平均数 p0
        mean = mean()

        # 取得蕴含 95% 概率的低 / 高点
        low\_p0, high\_p0 = l.nterval(.95)
        xo =nang(\_0, hih\_p0, 0.01)

        # 绘制 pdf
        ax.plot(x, self.pdf(x), 'r-')

        # 填充 95% 的区域
        between(x\_prob 0, sel.pdf(x\_pob)

        # 平均值
        ax.stem(\[mean\], \[sf.df(mea)

让咱们应用新代码绘制一些具备一序列参数的 Beta pdf。

对立先验

带点的垂直线显示 pdf 均值的地位。暗影区域示意对于给定的 α0 和 α1 值,概率为 95% 的(对称)区域。如果您想要平均值和置信区间的理论值,也能够获取这些值:

print("先验均值: {}".format(pri.mean()))

下面的其余先前示例也无效:

prior(5, 5)
plot()

por(2, 8)
iplot()

 

理解超参数所反映的先前假如的均值和不确定性很有用。

后验

最初,咱们为后验构建类。正如您所料,我将数据和先验作为参数,并从这些元素中提取后验所需的参数。

    def \_\_int\_(sf datprior):
        "" 后验。data: 一个数据样本的列表
        先验:β 先验类的一个实例
        """
        elflilihod = liliod(dta)
      sefprir = rio

        self.\_css\_steror()
    def \_pces\_posteror(slf):
        ""应用传递的数据和先验来解决后验。""

        # 从似然和先验中提取 n0, n1, a0, a1
        seln = slfliklihod.counts\['0'\]
        sel.n1 = elf.lkelihodcnts\['1'\]
        lfa0 = sf.prir.0
        self.a = sef.priora

        el0rv= beta(selfa0 + sfn0,
                         sef.a1 + slf.1)
    def interalself, prob):
        "" 含 \`prob\` 的 pdf 区域的端点。例如:interval(0.95)
        """def mean(sef):""" 返回后验平均数。"""def pdf(sef, p0):"""p0 处的概率密度。"""def plot(slf):"" 显示先验、似然和后验的图。""

        ## 先验
        # 失去先验平均数 p0
        pri_mean =eorman()

        #失去蕴含 95% 概率的低 / 高分值
        plo_p0,= interval(0.95)
        prob = arange(low\_p0, i\_hgh_0, 0.01)

        # 绘制 pdf
        plot(prior.pdf(x)

        # 填充 95% 的区域
        x.ll\_between(pri\_p)

        # 平均值
        astm(\[pri_mean\])

        
        ## 似然
        # 绘制似然图
        li = \[sel.likliood.pro\]
      

        # ## 后验

        #取得后验平均数 p0
        ostmen = mean()

        #失去蕴含 95% 概率的低 / 高点
        ow\_p0, \_high_p0 = interval(0.95)
       prob = np.rngest\_low\_p0po_highp0 0.01)

        # 绘制 pdf
        plot(x, slf.pd(x)

        # 填充 95% 的区域
        fil\_etween(pos\_xob, 0,self.df(pt_pr)
        # 平均值
        ax2\].t_mean\])

根本代码就是这样,让咱们做一些例子。

例子

让咱们从数据和对立先验的示例开始。

# 数据
data1 = \[0,0,0,0,1,1,0,0,0,1\]

# 先验
pro1 = prir(1, 1)

# 后验
ot1 = psteior(daa1, ior1)
plot()

这里须要留神的事项:

  • 先验是对立的。这意味着概率和后验具备雷同的形态。
  • 95% 的置信区间同时显示在先验和后验中。

接下来,让咱们思考具备不对立先验的雷同数据。数据集长度为 10,因而 n0+n1=10。让咱们用 α0+α1=10,设置先验,但先验在与似然不同的地位达到峰值(兴许有专家说这应该是先验设置):

# 先验
prir(4, 6)

# 后验
ps2 = postior(da1, pio2)
plot()

显然数据和专家在这一点上存在一致。然而,因为先验的权重设置为 10 并且数据序列的长度为 10,所以后验峰值位于先验峰值和似然峰值的两头。尝试应用这种成果来更好地了解先验超参数、数据集长度和后果后验之间的相互作用。

作为最初一个例子,咱们思考最初一个例子的两个变体,首先咱们应用对立先验:

# 设定概率为 0
p0 = 0.2
#设置 rng 种子为 2
n.rand.sed(2)
# 产生数据
dta2 =rando.i(\[0,1\], 500, p=\[p0, 1.-p0\])

# 先验
prior(1,1)

# 后验
poteir(daa2, pio3)

请留神,概率和后验峰值在同一个中央,正如咱们所冀望的那样。然而,因为数据集较长(500 个值),峰值要强得多。

最初,咱们在同一数据集上应用“谬误先验”。在这种状况下,咱们将放弃先验强度为 10,即 α0+α1=10:

# 先验
prior(6,4)
# 后验
poseor(data, pior4)

请留神,只管先验在谬误的地位达到峰值,但可能性和后验十分类似。这个例子表明,如果先验没有设置得太强,正当数量的数据应该产生不错的推理。一般来说,最好让 n0+n1>α0+α1 并思考先验和后验的形态。


 

最受欢迎的见解

1.matlab 应用贝叶斯优化的深度学习

2.matlab 贝叶斯隐马尔可夫 hmm 模型实现

3.R 语言 Gibbs 抽样的贝叶斯简略线性回归仿真

4.R 语言中的 block Gibbs 吉布斯采样贝叶斯多元线性回归

5.R 语言中的 Stan 概率编程 MCMC 采样的贝叶斯模型

6.Python 用 PyMC3 实现贝叶斯线性回归模型

7.R 语言应用贝叶斯 层次模型进行空间数据分析

8.R 语言随机搜寻变量抉择 SSVS 预计贝叶斯向量自回归(BVAR)模型

9.matlab 贝叶斯隐马尔可夫 hmm 模型实现

正文完
 0