输出笔记:贝叶斯定理Python实现+个人理解

​写这篇笔记的来源:

image

昨天晚上在朋友圈刷到了朋友用R画的贝叶斯网络(也就是上图,图片已拿到授权。选的节点很多,个人觉得像宇宙,交叉的点不断的向外边发送信号,还怪好看的)。这时想起了,自己收藏夹有贝叶斯定理的解析(以前只是收藏了,没看,逃。)

然后用Python实现一个简单的贝叶斯定理的脚本。也是为了验证下是否理解了贝叶斯定理。

贝叶斯定理介绍:

Steve很害羞而且性格孤僻,虽然乐于助人,但却对周围的人或现实世界不太感兴趣,是一个温顺而又井井有条的人。他需要什么事都有条理、结构清晰、且热衷于钻研细节。

你觉得下面哪种说法可能性更大?

Steve是一个图书馆管理员----Steve是一个农民

这是kahnman和tversky的一个实验,根据他们的实验结果。当人们知道Steve是一个温顺而又井井有条的人的时候,大部分人都会说,Steve更可能是图书馆管理员,毕竟相较于农民,这更符合图书馆管理员的形象。

然而问题的关键不在于,人们对图书馆管理员和农民的特征形象认识是否有偏差。

而是,在做判断的时候,没人把农民和图书馆的比例信息考虑进去。

根据他们的论文给出:在美国,农民与图书馆管理员的数量之比是20:1。

我们是否在判断的时候,加入了比例因素的影响。

根据这个比例,我们假设有10名图书馆管理员和200名农民。当你看到“Steve是一个温顺而又井井有条的人”的时候,我们假定你第一感觉有40% 的图书馆管理员符合这个描述,而只有10%的农民符合这个描述。

这意味着,在这120个样本,大约有4名图书馆管理员符合这个描述,而大约有20名农民符合这个描述。我们从这24人随便抽一个,抽到图书馆管理员的概率16.7%。

即使有40%的图书馆管理员符合这个描述,比农民比例多了4倍,然而农民基数大呀。

贝叶斯有个基本理论:新证据不能直接凭空决定你的想法,而是根据新证据去更新你之前的判断(先验概率)。

例如上面的例子,我们限制了概率空间,再考虑比例。

贝叶斯给了我们一个新的思考方向,下面是贝叶斯公式:

image

P(A|B) 是B事件发生后A事件的概率。即B事件是已知的,而A事件未知。

P(A) 是先验概率"(Prior probability)即我们在不知道B事件发生的前提下,对A事件发生概率的一个主观判断.

这个判断并不是凭空的,例如未上线业务,没有数据的业务,我们可以用行业的平均值,或者竞品所采用的数值,作为初始指标,在后期根据运行情况,不断改变这个初始指标。

P(B|A)/P(B) 我们可以理解为新证据、新数据。根据新数据,算出一个影响因子。将P(A) 乘以这个影响因子,不断改变概率,使其符合真实概率。

P(B) 有全概率公式。P(B) = P(B|A1) * P(A1) + P(B|A2) * P(A2)

以+号为中间点,分为两部分。假如A1和A2构成一个问题的全部(即全部的样本空间)。那么事件B的概率,就等于A1乘以B对A1的条件概率+A2乘以B对A2的条件概率。

案例:

假设有两碗曲奇饼,碗A包含30个香草曲奇饼和10个巧克力曲奇饼,碗B这两种曲奇饼各20个。

现在假设你在不看的情况下随机地挑一个碗拿一块饼,得到了一块香草曲奇饼。

问题:从碗A拿到香草曲奇饼的概率是多少

我们先假设,A事件为从碗A,A'事件为从碗B,B事件为拿到香草曲奇饼

image

P(A) = P(A') = 1/2

因为只有两个碗,我们假设先验概率为1/2

P(B|A) = 30 / 40 = 3/4

这是从碗A拿到香草曲奇饼的概率,有30块香草曲奇饼,总共有40块饼干

P(B) = P(B|A)P(A) + P(B|A')P(A')= (3/4)(1/2) + (1/2)(1/2) = 0.625

这是全概率公式。+号左边的数值上边已经计算,而右边的是从碗B拿到香草曲奇饼的概率和先验概率相乘。

P(A|B) = P(A) * P(B|A) / P(B) = (1/2) * (3/4) / (5/8) = 0.6

将数字代入公式,求的从碗A拿到香草曲奇饼的概率是0.6

以下是Python代码

class simple_Bayesia(object):
    """docstring for simple_Bayesia"""
    def __init__(self):
        super(simple_Bayesia, self).__init__()
        self.container = dict()
    def set(self,prior_A,prior_B,bowl_A_vanilla,bowl_A_Chocolate,bowl_B_vanilla,bowl_B_Chocolate):
        self.container['prior_A'] = prior_A # A的先验概率
        self.container['prior_B'] = prior_B # B的先验概率
        self.container['bowl_A_vanilla'] = bowl_A_vanilla # A碗的香草个数
        self.container['bowl_A_Chocolate'] = bowl_A_Chocolate # A碗的巧克力个数
        self.container['bowl_B_vanilla'] = bowl_B_vanilla # B碗的香草个数
        self.container['bowl_B_Chocolate'] = bowl_B_Chocolate # B碗的巧克力个数
        self.container['bowl_A']= self.container['bowl_A_vanilla']+self.container['bowl_A_Chocolate']
        self.container['bowl_B']= self.container['bowl_B_vanilla']+self.container['bowl_B_Chocolate']
​
    def print(self,bowl,cookie_name):
        print("从碗{}获取{}的概率是:".format(bowl,cookie_name))
        print(self.container['prior_'+bowl]*self.likelihood(bowl,cookie_name))
    def likelihood(self,bowl,cookie_name):
        #P(B|A) / P(B)
        if bowl=='A':
            other = 'B'
        else:
            other = 'A'
        P_B_A = self.container['bowl_'+bowl+'_'+cookie_name]/self.container['bowl_'+bowl]
        P_B = (self.container['bowl_'+bowl+'_'+cookie_name]/self.container['bowl_'+bowl])*self.container['prior_'+bowl] \
        + (self.container['bowl_'+other+'_'+cookie_name]/self.container['bowl_'+other])*self.container['prior_'+other]
        return P_B_A / P_B
a = simple_Bayesia()
a.set(1/2,1/2,30,10,20,20)# 依次传递「A的先验概率、B的先验概率、A碗的香草个数、A碗的巧克力个数、B碗的香草个数、B碗的巧克力个数」
a.print('B','Chocolate')# 依此传递「从碗{}获取{}的概率,{}里的值」

运行结果:

image

参考文献:

1.https://www.youtube.com/watch?v=HZGCoVF3YvM

2.https://www.bilibili.com/video/BV1R7411a76r

3.https://zhuanlan.zhihu.com/p/27012448

4.https://zhuanlan.zhihu.com/p/37768413

你可能感兴趣的:(输出笔记:贝叶斯定理Python实现+个人理解)