5.1 胜率
通常用[0,1]之间的数字来表示概率,不过这并非唯一的方法。也可用博彩业的另一种概率表示形式——胜率(odd)。
胜率是一个事件可能发生的概率与不发生的概率比值。
假如球队A同球队B比赛,获胜的概率为75%,我会说他们的胜率是3:1。
但当概率较低,通常称之为赔率(odd against),而不是胜率(odds in favor)。例子中球队B获胜的概率为25%,我会说他们的赔率为3:1。
即胜率和概率是相同信息的不同表示形式。
5.2 贝叶斯定理的胜率形式
已知贝叶斯定理的概率形式:
在相同观察数据的前提D下,如果我们有A和B两个假设,将后验概率相除的比值如下:
请注意等式中出现的标准化常数p(D)。
若A和B是互斥且穷尽的,就意味着P(A)=1-P(B),因此我们可以将先验的比率、后验的比率重写成胜率。将A的胜率写成o(A),得到:
从字面形式上,说明了后验胜率是先验胜率乘以似然比。这就是贝叶斯定理的胜率表示形式。
例如:
有两个盒子,盒子1中有香草饼30个,巧克力饼10个。盒子2中的两种饼干各20个。
现在假如你随意选择一个盒子,然后选择一个饼干。如果香草饼,则它来自盒子1的概率是多少?
取到盒子1的先验概率为50%,所以盒子A的胜率为1。
所以后验概率为3:2,对应概率为3:5。
5.3 奥利弗的血迹
以下是来自麦凯的《信息理论、推理和学习》的另一个问题。
在一个犯罪现场,有两个人留下血迹,一个嫌犯奥利弗是O型血。现场发现的血迹分别为O型(当地有60%的人口血液类型)和AB型(仅1%的罕见类型)。
那么这些数据是否支持奥利弗是嫌犯?
要回答这个问题,我们需要想想”数据支持了假设“这到底意味着说明。直觉上,相比之前,如果某一假设随着数据的出现而呈现更大的可能性,我们就说”数据支持了假设“。
在饼干的问题上,概率为3:5。因此我们说香草饼干这一个数据作为证据支持其来自盒子1。
贝叶斯定理的胜率形式提供了一种方法,使这一直觉更加准确。
回顾一下公式:
除以o(A):
等式左边是后验胜率和前验胜率的比值。右边是似然比,也被称为 贝叶斯因子。
如果贝叶斯因子的值大于1,则意味着数据更支持假设A而不支持假设B。
现在,我们回到原来的问题。如果奥利弗是在嫌犯,就解释了样本O型血的来源,因此数据的概率就是在人群中挑中一个AB型血的人概率1%。
如果奥利弗没有在现场留下血液,我们就要对连个样本及逆行解释。假设在人群中任意选取两人,有多大可能性找到O和AB型的人呢?
如果不是奥利弗的血液,数据的似然度还会高些,所以这个血液证据并没有支持奥利弗是嫌犯。
5.4 加数
贝叶斯统计的基本操作是UPdate,这需要先验概率和一组数据,然后产生一个后验分布。但是,实际解决问题中通常涉及其他操作,包括缩放、加法和其他算数运算、最大值和最小值,还有混合运算。
本章主要介绍加法和最大值。
前提,我们对三个6面筛子的总和感兴趣,有两种方法可以计算其总和分布。
1. 模拟:
给定一个表示筛子面分布的Pmf,可以绘制随机样本,把他们都加起来,累加每次模拟求和的分布。
2. 枚举:
给定两个Pmfs,可以枚举所有可能的数值对,并计算其和的分布。(后面会以连加的方式得到3个筛子的总体分布)
thinkbays提供了这两个函数。首先定义一个类来表示单个骰子:
class Die(thinkbays.Pmf):
def __init__(self, sides):
thinkbays.Pmf.__init__(self)
for x in xrange(1, sides + 1):
self.set(x, 1)
self.Normalize()
现在,可以创建一个6面骰子:
d6 = Die(6)
然后使用thinkbays.SampleSum产生1000次转动3个骰子的样本。
dice = [d6] * 3
three = thinkbays.SampleSum(dice, 1000)
SampleSum以分布的列表(Pmf或 Cdf 对象)和样本大小n为参数。它产生n次随机样本的和(单次模拟的汇总——转动3次骰子),并将其分布作为一个Pmf对象返回。
def SampleSum(dists, n):
pmf = MakePmfFromList(RandomSum(dists) for i in xrange(n))
return pmf
SampleSum使用RandomSum,也在thinkbays.py中:
def RandomSum(dists):
total = sum(dist.Random() for dist in dists)
return total
RandomSum在每个分布中调用Random然后汇总结果。
模拟的缺点是得到的结果至少近似正确的,随着n的变大,结果会更准确,但运行时间也会增加。
另一种方法是枚举所有大的值,并计算每对概率和总和。这在Pmf.add上实现:
def __add__(self, other):
pmf = Pmf()
for v1, p1 in self.Items():
for v2, p2 in self.Items():
pmf.Incr(v1+v2, p1+p2)
return pmf
self是一个Pmf对象,other可以是Pmf或者其他提供条目的对象。
下面是如何使用它:
three_exact = d6 + d6 + d6
当在Pmf中应用+操作符时,Python调用add函数。在这个例子中,add被调用了两次。
5.5 最大化
有三种方法计算最大值的分布。
1. 模拟
给定一个Pmf,代表单一选择的分布,可以生成随机样本,找到最大值和模拟最大值的累计分布。
2. 枚举
给定两个Pmf,可以枚举所有可能的数值对,并计算分布的最大值。
3. 指数计算
如果我们将一个Pmf转换为
Cdf
,有一个简单而有效的算法查找最大的
Cdf
。
这里不对方法1和方法2多做解释,对于指数计算部分,如果我们转换Pmf到
Cdf
,这里首先给出累积分布函数的定义:
如果我从 CDF 1中取出X,从 CDF 2中取出Y,计算最大值 Z=max(X,Y) ,则Z小于等于5的概率是多少?
如果选择X和Y是独立行为
CDF 3(5) = CDF 1(5) CDF 2(5)
其中
CDF
3是Z的分布。
我们可以一般化5为任意值的情况:
CDF 3(z) = CDF 1(z) CDF 2(z)
特例情况下是我们从同一分布中选择k值,
CDF k(z) = CDF 1(z)k
因此,为了求k的最大值的分布,我们可以枚举给定 Cdf 的概率再将其变化为k的次幂。 Cdf 提供了一种方法,该方法如下:
class $Cdf$
def Max(self, k):
$cdf$ = self.copy()
$cdf$.ps = [p**k for p in $cdf$.ps]
return $cdf$
5.6 混合分布
假设有一个骰子,清单如下:
5个——4面骰子
4个——6面骰子
3个——8面骰子
2个——12面骰子
1个——20面骰子
从盒子中选择一个骰子转动,如果确定骰子,很容易确定分布。n面骰子产生一个均匀从1到n的分布。
若随机选择骰子,由此产生的分布测试有不同上界的均匀分布的混合分布。
在一般情况下,这类混合量不适合任何简单的数学模型,但它可以从对PMF直接计算得到。跟之前的小节内容一样,一个选择是模拟,生成一个随机样本计算模拟样本的PMF。
但为了得到一个确切的解法,让我们选从只有两个骰子的简单版本开始,一个6面和一个8面。可以用Pmf来表示每个骰子。
d6 = Die(6)
d8 = Die(8)
然后创建一个Pmf来表示这一混合分布:
只有两个骰子的简单版本开始,一个6面和一个8面。可以用Pmf来表示每个骰子。
mix = thinkbayes.Pmf()
for die in [d6, d8]:
for outcome, prob in die.Items():
mix.Incr(outcome, prob)
mix.Normalze()
第一个循环枚举骰子,第二个循环枚举循环骰子结果和概率。在循环内部汇聚了两个分布的贡献。
更一般的,假如事先知道选中每一个骰子的概率,就能对结果进行相应的加权。
首先创建一个映射了骰子和骰子被讯中概率的Pmf对象:
只有两个骰子的简单版本开始,一个6面和一个8面。可以用Pmf来表示每个骰子。
pmf_dice = thinkbayes.Pmf()
pmf_dice.set(Die(4), 2)
pmf_dice.set(Die(6), 3)
pmf_dice.set(Die(8), 2)
pmf_dice.set(Die(12), 1)
pmf_dice.set(Die(20, 1)
pmf_dice.Normalize*()
于是,我们得到计算混合分布算法的一个更通用版本:
mix = thinkbayes.Pmf()
for die, weight in dice.Items():
for outcome, prob in die.Items():
mix.Incr(outcome, weight*prob)