贝叶斯思维(实例1)——贝叶斯基础框架

来源:互联网 发布:红警3 for mac版 编辑:程序博客网 时间:2024/05/16 11:22

所有贝叶斯统计的方法都基于贝叶斯定理,因此我们从概率、条件概率开始,然后到贝叶斯定理,最后讨论贝叶斯统计的内容。

概率表示0和1之间的数字(包括0和1),含义是某一事件或者预测行为的可信程度。

条件概率是带有某些(前提条件)背景约束下的概率问题。通常条件概率的记号是P(A|B),表示在给定B条件下A事件发生的概率。

联合概率是指两个事件同时发生的概率。P(A和B)是A和B事件的发生都为真的概率。通常意义下,联合概率表述为:
P(A and B) = P(A)P(B|A)

贝叶斯定理表达式为:


  • p(H)称为先验概率,即在得到新数据前某一假设的概率

  • p(H|D)称为后验概率,即在看到新数据后,我们要计算的该假设的概率

  • p(D|H)是该假设下得到这一数据的概率,称为似然度

  • p(D)是在任何假设下得到这一数据的概率,称为标准化常量

Monty Hall难题

蒙蒂大厅(Monty Hall)是游戏节目“Let's Make a Deal”的主场,蒙蒂大厅难题的游戏规则是:

  • 蒙蒂向你示意三个关闭的大门,然后告诉你每个门后都有一个奖品:一个奖品是一辆车,其他两个是不值钱的奖品。奖品随机配置。

  • 游戏的目的是要猜哪个门后有车,如果猜对了就可以拿走车。

  • 你先挑选一扇门,姑且称为A门,其他两个为门B和C

  • 在打开你选中的门之前,为了增加悬念,蒙蒂会先打开B或C中一个没有车的门来增加悬念(如果车实际在A门后,那么打开B或C都是安全的,可以随意选择一个)。

  • 然后蒙蒂给你一个选择,坚持最初的选择还是换到剩下未打开的门。

问题是,你应该“坚持”还是“换”?有没有区别?

运用贝叶斯定理,我们可以将这个问题分解成几个简单部分。本例中D为两个部分:蒙蒂打开了门B,而且没有车在后面。接下来,我们定义三个假设:A、B和C,表示假设车在门A、门B或门C后面,采用表格法:

先验概率p(H)似然度p(D|H)p(H)p(D|H)后验概率p(H|D)假设A = 1/31/21/61/3假设B = 1/3000假设C = 1/311/32/3

先验很容易填写,因为我们被告知奖品是随机配置的,表明该车可能在任何门后。

定义似然度需要考虑一些,我们确信正确的似然度如下:

  • 考虑假设A:如果车在门A后,蒙蒂可以安全地打开门B或C。所以选择门B的概率是1/2。

  • 考虑假设B:如果车在门B后,蒙蒂不得不打开门C,这样打开门B的概率是0(也就是假设的似然度为0)。

  • 考虑假设C:如果车在门C后,蒙蒂打开门B的概率为1。

第三列的总和为1/2,除以后得到p(A|D)=1/3,p(C|D)=2/3,所以最好换个选择。


为了解决蒙蒂大厅问题,我们定义一个新类monty,monty需要继承的基础类为:

import logging#定义字典对象class _DictWrapper(object):    def __init__(self, values=None, name=''):        self.name = name        self.d = {}        self.log = False        if values is None:                        return        init_methods = [            self.InitPmf            ]                for method in init_methods:                        try:                method(values)                                break            except AttributeError:                                continue        if len(self) > 0:            self.Normalize()                        #用Pmf初始化对象            def InitPmf(self, values):        for value, prob in values.Items():            self.Set(value, prob)                            #获取未排序的值列表    def Values(self):        return self.d.keys()                            #获取未排序的值/概率对    def Items(self):        return self.d.items()                            def Set(self, x, y=0):        self.d[x] = y                            def Mult(self, x, factor):        self.d[x] = self.d.get(x, 0) * factor                            #返回map格式的概率总和    def Total(self):        total = sum(self.d.itervalues())                return total                    #概率质量函数对象class Pmf(_DictWrapper):        #获取x所对应的概率值    def Prob(self, x, default=0):        return self.d.get(x, default)        #pmf的归一化    def Normalize(self, fraction=1.0):        if self.log:                        raise ValueError("Pmf is under a log transform")        total = self.Total()                if total == 0.0:                        raise ValueError('total probability is zero.')            logging.warning('Normalize: total probability is zero.')                        return total        factor = float(fraction) / total                for x in self.d:            self.d[x] *= factor                          eturn total

monty类的具体定义如下:

#代表一套假设及其概率class monty(Pmf):        #初始化分配    def __init__(self, hypos):        Pmf.__init__(self)                for hypo in hypos:            self.set(hypo, 1)        self.Normalize()                #更新基于该数据的每个假设    def Update (self, data):        for hypo in self.Values():            like = self.Likelihood(data, hypo)            self.Mult(hypo, like)        self.Normalize()              #计算似然度      def Likelihood(self, data, hypo):        if hypo==data:                          return 0        elif hypo=='A':                           return 0.5        else:                        return 1

monty对象是一个映射假设到概率的Pmf对象,__init__方法给每个假设赋予相同的先验概率。如:

hypos='ABC'pmf=monty(hypos)

monty类提供了Update方法,它以data为参数并修正相应的概率。

data='B'pmf.Update(data)

Update遍历suite中的每个假设,并将其概率乘以数据在某一假设下的似然度。

最后,打印输出结果:

for hypo, prob in pmf.Items():        print hypo, prob

答案是:

A 0.333333B 0.0C 0.666667


参考文献:

    贝叶斯思维.  Allen B.Downey.  许杨毅 译