贝叶斯定理_python实现_1_贝叶斯基础
前言
与贝叶斯统计的方法都基于的是贝叶斯定理,贝叶斯定理是条件概率的演算的重要基础,这里我们先回顾概率基础,再理解贝叶斯公式原理。
一、概率
- ‘’S‘’为样本空间,是随机事件所有事件发生的集合。从集合的角度看,把ABC三个圆围成的区域叫做随机事件S的样本空间,A、B、C均是S的子集。
- ‘’ P ( A ∩ B ) P(A \cap B) P(A∩B)‘’表示A、B事件同时发生的概率(联合概率)。如果B事件的发生不影响A事件的发生的概率,则称A、B事件相互独立,此时 P ( A ∣ B ) = P ( A ) P(A|B)=P(A) P(A∣B)=P(A)。只有在这种情况下,A、B事件同时发生的联合概率才是: P ( A ∩ B ) = P ( A ) ⋅ P ( B ) P(A \cap B)=P(A)·P(B) P(A∩B)=P(A)⋅P(B),否则由于两个事件存在相互依赖,联合概率的计算公式应为: P ( A ∩ B ) = P ( A ) ⋅ P ( B ∣ A ) P(A \cap B)=P(A)·P(B|A) P(A∩B)=P(A)⋅P(B∣A)
- ‘’ P ( A ∣ B ) P(A|B) P(A∣B)‘’表示如果B事件发生的条件下,A事件发生的概率,称为条件概率。这相当于将计算“A事件发生”概率的样本空间限制在“如果B事件发生”的情况下。一般说到条件概率这一概念的时候,事件A和事件B都是同一实验下的不同的试验结果。(有一些问题可能让读者觉得要计算的两个事件不像是同一试验下的结果,从而不知道如何计算条件概率,其实这和你如何定义样本空间有关,这里不展开谈论)
二、贝叶斯定理
- 贝叶斯定理的实际含义描述的是:人们如何根据现有资料对目前在某一事件发生的相信程度(信念)进行更新。(这种对贝叶斯公式的理解被称为“历时诠释”)
- 它的结构分为四个部分:先验概率
P
(
H
)
P(H)
P(H)、后验概率
P
(
H
∣
D
)
P(H|D)
P(H∣D)、似然
P
(
D
∣
H
)
P(D|H)
P(D∣H)、标准化常量
P
(
D
)
P(D)
P(D)。其中,
P
(
D
∣
H
)
P
(
D
)
\frac{P(D|H)}{ P(D)}
P(D)P(D∣H)也称为修正因子,更新人们对事物的信念
P ( H ∣ D ) = P ( H ) ⋅ P ( D ∣ H ) P ( D ) P(H|D) = \frac{P(H) ·P(D|H)}{ P(D)} P(H∣D)=P(D)P(H)⋅P(D∣H)
- 先验(prior)概率:表示在得到新数据前对某一事件发生概率的判断
- 后验(posterior)概率:表示了解了新数据后对该假设概率的新的判断
- 似然/可能性(likelihood):表示在该假设下得到数据的概率
- 标准化常量:表示在样本空间的所有事件都可能发生的情况下,得到这一数据的概率
- 很多情况下,先验概率偏主观,人们可能使用不同背景信息而做出主观判断;似然的计算很简单,它可以从数据B中统计出在A假设情况下的目标事件的比率;标准化常量是较难计算的,一般而言我们通过设定一组互斥的假设集通过全概率公式获取它。
三、应用案例一:Monty Hall问题
3.1 问题描述
我们一定都接看过这样一种电视节目中的嘉宾猜谜环节:主持人将大奖放于A、B、C三个门背后的其中一扇门,其余两扇门的奖品价值远远不及。选手首先选择了A门作为自己竞猜的选择,然后主持人会打开剩余门中没有奖品的一扇门B门,然后问选手是否更换自己的选择。于是,问题来了:选手究竟该不该换?是否换与不换在获奖概率上有区别?
3.2 解答
很多人直觉认为在主持人开启一扇门后,剩余两扇门中奖概率都是50%,没有区别。但是事实上运用贝叶斯定理获得的结果大不相同。我们采用表格法对运用贝叶斯定理下各事件的概率进行整理(表3-1),计算整理的过程如下描述。
首先我们设定三个互斥的假设:A、B、C(便于后续计算标准化常量
P
(
D
)
P(D)
P(D))。假设A定义为大奖在A门后,假设B定义为大奖在B门后,假设C定义为大奖在C门后。
我们的H事件描述为“选择了A门并有奖”,D事件为“B门被揭示且没有大奖”(可以理解为主持人选择了一个没有大奖的门揭示)。我们计算后验概率即为“B门没有大奖情况下,选择A门有大奖的概率”。
参赛选手在最开始没有被透露任何信息的时候,他对每个门有大奖的信念是
1
3
\frac{1}{3}
31,即我们相信每个假设的概率是
1
3
\frac{1}{3}
31。为了计算知晓B门没有奖品后的信念变化结果,我们需要进一步计算似然和标准化常量。
在定义似然度时需要一些思考。假设A下的似然度
P
(
D
∣
H
)
P(D|H)
P(D∣H) 描述为:“大奖就在A门后的情况下,主持人选择揭示B作为无奖结果的概率”,因为A假设下(样本空间进行了限制),B、C门都没有大奖,因此主持人揭示其中任何门的概率均为
1
2
\frac{1}{2}
21;B假设下,B门有大奖,但是发生的事件D表明B门没有大奖,因此这一假设下的可能性为0,我们在根据数据D知晓该假设可能性后就会否定该假设,即该假设下的后验概率为0。在C假设下,C门有大奖,又由于选手已经选择了A门,那么必然主持人揭示B门作为没有大奖门的可能性为1。至此,我们写出了每个假设下的似然度。标准化常量的计算即将这三个假设下
P
(
H
)
P
(
D
∣
H
)
P(H)P(D|H)
P(H)P(D∣H)之和计算出来,即
P
(
D
)
=
Σ
P
(
H
)
P
(
D
∣
H
)
P(D)=\Sigma P(H)P(D|H)
P(D)=ΣP(H)P(D∣H) 。然后根据
P
(
D
)
P(D)
P(D)计算后验。
因此我们可以看到有证据D之后,信念发生了变化,应该更换选择。
Hypos | 先验概率 P ( H ) P(H) P(H) | 似然 P ( D ∥ H ) P(D\|H) P(D∥H) | P ( H ) P ( D ∥ H ) P(H)P(D\|H) P(H)P(D∥H) | 后验概率 P ( H ∥ D ) P(H\|D) P(H∥D) |
---|---|---|---|---|
假设A | 1/3 | 1/2 | 1/6 | 1/3 |
假设B | 1/3 | 0 | 0 | 0 |
假设C | 1/3 | 1 | 1/3 | 2/3 |
3.3 python实现
使用python实现本案例的计算可以使用Allen B. Downey开发的ThinkBayes2.模块。本案例主要是用ThinkBayes2模块中定义的概率质量函数类Pmf()
,为了计算后验概率,我们要调用该类的update
方法,likehood
方法。
from thinkbayes2 import Pmf
class Monty(Pmf):
"""将车可能处在的位置映射到概率"""
def __init__(self, hypos):
"""初始化分布.
hypos: 一系列假设
"""
Pmf.__init__(self)
for hypo in hypos:
self.Set(hypo, 1)
self.Normalize()
def Update(self, data):
"""根据数据更新每个假设.
data: 字符 'A', 'B', or 'C'
"""
for hypo in self.Values():
self[hypo] *= self.Likelihood(data, hypo)
self.Normalize()
def Likelihood(self, data, hypo):
"""在假设下计算数据的可能性.
hypo: 把奖品所在的门的名称串对应起来
data: 蒙蒂打开的门的名字
"""
if hypo == data:
return 0
elif hypo == 'A':
return 0.5
else:
return 1
pmf = Monty('ABC')
pmf.Update('B')
pmf.Print()
A 0.3333333333333333
B 0.0
C 0.6666666666666666
四、应用案例二:猜骰子问题
4.1 问题描述
- 现在有一批不同规格的骰子各一个:4面骰子(D4),6面骰子(D6),8面骰子(D8),12面骰子(D12),20面骰子(D20)
- 我们开始进行试验:投掷骰子,然后根据结果计算骰子为Dx的概率。
- 第1次试验结果:第一次投出点数6,请问为每种筛子的概率是多少?
- 第2-7次试验结果:第2-7次投出点数
6,8,7,7,5,4
,请问为每种筛子的概率是多少?
4.2解答
- 本例使用 thinkbayes2.py 中的
Suite
类,它是一个抽象类,这里我们要使用Suite
接口中的Update
方法和likehood
方法,前者在Suite
中已经实现,后者likehood
需要用户在自己的具体类中继承Suite
并实现。
4.3 python实现
from thinkbayes2 import Suite
class Dice(Suite):
def Likelihood(self, data, hypo):
if hypo < data:
return 0
else:
return 1/hypo
suite = Dice([4, 6, 8, 12, 20])
suite.Update(6)
suite.Print()
4 0.0
6 0.3921568627450981
8 0.29411764705882354
12 0.19607843137254904
20 0.11764705882352944
for roll in [6, 8, 7, 7, 5, 4]:
suite.Update(roll)
suite.Print()
4 0.0
6 0.3921568627450981
8 0.29411764705882354
12 0.19607843137254904
20 0.11764705882352944
参考文献
[1]: Downey, Allen. Think Bayes: Bayesian statistics in python. " O’Reilly Media, Inc.", 2013.