贝叶斯思维:统计

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 167


 


 录

内 要

1章
贝
1.1
条件概率
1.2
 合概率
1.3
 饼问题
1.4
贝
1.5
历时
1.6
M&M 问题
1.7
Monty
Hall 题
1.8
讨
2章
统
2.1
分
2.2
 饼问题
2.3
贝 架
2.4
Monty
Hall 题
2.5
封 架
2.6
M&M 问题
2.7
讨
2.8
练习
3章

3.1
骰子问题
3.2
 问题
3.3
怎 看待先 概率?
3.4
其他先 概率
3.5

3.6
 积分
3.7
德军 克问题
3.8
讨
3.9
练习
4章
 进
4.1
欧元问题
4.2
后 概率的概
4.3
先 概率的 没
4.4
优
4.5
Beta分
4.6
讨
4.7
练习
5章
 率和
5.1
 率
5.2
贝 的 率形式
5.3
奥利 的 迹
5.4

5.5
最大
5.6
 合分
5.7
讨
6章
决 分
6.1
“ 的 格”问题
6.2
先 概率
6.3
概率密度
6.4
PDF的 示
6.5
选手
6.6
 然度
6.7
更新
6.8
最优出
6.9
讨
7章

7.1
波 顿 熊 问题
7.2
 松过
7.3
后
7.4
入球分
7.5
 的概率
7.6
 然 法则
7.7
讨
7.8
练习
8章
 察 的 差
8.1
红线问题
8.2
 型
8.3
 待时
8.4
 待时
8.5
 到达率
8.6
消除不
8.7
决 分
8.8
讨
8.9
练习
9章
 维问题
9.1

9.2
Suite对象
9.3
三 学
9.4
 然度
9.5
 合分
9.6
条件分
9.7

9.8
讨
9.9
练习
10章
贝 近
10.1
变异 说
10.2
均 和 准差
10.3
更新
10.4
CV的后 分
10.5
 据下溢
10.6
对 然
10.7
一个小的优
10.8
ABC(近 贝 )
10.9
 的可靠
10.10
谁的变异 更大?
10.11
讨
10.12
练习
11章

11.1
 到欧元问题
11.2
来一个 平的对
11.3
三
11.4
讨
11.5
练习
12章
证据
12.1
 读SAT成
12.2
 例得分SAT
12.3
先
12.4
后
12.5
一个更好的 型
12.6
 准
12.7
效率的后 分
12.8
 分
12.9
讨
13章
 真
13.1
肾 的问题
13.2
一个 型
13.3
更普 的 型
13.4
 现
13.5
缓 合分
13.6
条件分
13.7

13.8
讨
14章
 型
14.1
 器问题
14.2
 的开始
14.3
分 型
14.4
一个小优
14.5
抽取后
14.6
讨
14.7
练习
15章
 多维问题
15.1
 部细菌
15.2
狮子, 和熊
15.3
分
15.4
 抽
15.5
优
15.6
 的 结构
15.7
 一个问题
15.8
还有工 要做
15.9
肚 据
15.10
 分
15.11
 合后
15.12

15.13
讨



译后记
迎来到异步社 !

:贝 维:统 的Python学习法

ISBN:978-7-115-38428-7

本 人 电出 社发行 字 所有

购买的人 出 社 子 个人 用,未 ,不得以 式 和 内 。

我们愿 读 有这 的良 和 , 我们共 护 产 。

购买 有 为,我们可能对 用户 施 不 闭 维 措施,并可能 究法
责 。

•
 着
 
 
 
 [美]
Allen
B.
Downey


 
译
 
 
 
 许


 
责 编 
 王峰松

•
 人 出 社出 发 
 
 北 台 成 路11


 
 编
 100164

 子 件
 315@ptpress.com.cn


 
 址
 http://www.ptpress.com.cn

•
 读 服 热线:(010)81055410


 
反盗 热线:(010)81055315


Copyright
©2013
by
O’Reilly
Media,
Inc.

Simplified
 Chinese
 Edition,
 jointly
 published
 by
 O’Reilly
 Media,
 Inc.
 and
 Posts
 &
 Telecom
 Press,
 2014.
Authorized
translation
of
the
English
edition,
2013
O’Reilly
Media,
Inc.,
the
owner
of
all
rights
to
publish
and
sell
the
same.

All
rights
reserved
including
the
rights
of
reproduction
in
whole
or
in
part
in
any
form.

本 中文简 O’Reilly
Media,
Inc. 人 电出 社出 经出 面许可 对本 的


分不得以 方式复 播

所有


这 在帮助那 希望用 学工 决 问题的人们, 有的要 可能就是 一点概率 和
。贝 法是一 常 的利用概率学 去 决不 问题的 学 法,对 一个 专业
人 ,应 悉其在诸 器翻译、语 、 件 常 的 领域的应用。

上会扩大你的 , 不是一个 专业人 ,你也可以看到在 环境下(


界大 德军 克问题),法 问题上(肾 的 证),体育博 领域中( 熊 和 人 NHL
问题)贝 法的威 。怎么 有 的 息 断德军 甲部 的 ?你 支 的球 有多大可能 得
军?在《龙 地下 》勇 中,你应 对游戏 色 的最大 有怎 的 期?甚至在普通的 射击
游戏中,拥有一 贝 维也能帮助你 游戏 平。

除此以外, 在共 15章的篇幅中讨 了怎 决十 个现 生活中的 问题。在这 问题的


决过 中, 还 默 地帮助读 形成了 决 的 法 , 误差和 误差怎么取 ,怎 为
体问题创 学 型, 住问题中的 要矛盾( 型中的 键参 ), 一步一步地优 证
型的有效 。在这个 上,这 是一 学 的成功 。

推 序
很多人 界 为基 的、 的,非一 、非黑 白的。 是真 的 界却是非常 杂
的,不是一 个 式可以 美总结概 的。就像我们的 成 和我们的学习 平, 有很大的 ,
是最后 会受到很多 的 ( 体状况,是 休息好了,心情,天 ),进 得我们的最
成 在真 平上下有很大的波动。这就像我们分 很多事情时, 常得到的结 ,“既有必然 ,
有偶然 ”。

这个时 ,基 概率和统 的 法给了我们很多的帮助。很多时 ,我们不能给出 一个人、 一件


事的 结 。 是 我们 察大量的 事件后,我们就会发现 一个集体的 上的 是 在的。
个事件 可能得到不 的结 ,这 结 以最有可能的结 为中心,服 一 的概率分 。了 这
分 据, 我们更 和 期真 界的多 形。

顾在进 自然语 过 中 过的路,我们就会发现 研究 则到研究统 的转变。最


,研究人 都 为,语 是基 语法 则。这个也很 , 为我们学习语 的时 ,总是
词,学语法,然后 握语 。基 这 维,自然语 历了多年的发展后, 到了巨大的挑 。那
就是 便语法 则 非常 杂, 然不能 大多 的语 情况。 结 上 ,自然语 的准
度 人类,不 有真 的 用 。 后,有一 学 开始 蹊径,基 统 的 路进 探 。
语 是根据人类 通 自然发生,然后 有总结出来的语法呢?基 这 想,研究人 语法
则,开始创 基 统 的 型。他们 用了大量的真 据,分 个词和 后的词出现的统
,用贝 法以 科 过 ,创 了新的自然语 型。这一 ,语 准 率有了巨大
的 ,进 达到可以 用的要 。今天, 我们 用 歌翻译、苹 的Siri语 服 的时 ,后 都有
基 统 的 型的功 。

还有很多的真 界的事情都是这 的, 路上的交通是 、银 的时 、球 的 结


,都是以一 概率的形式出现的。了 贝 法,也是了 真 界 的一 有效 径。 中也
了很多的真 例来告诉我们,贝 法和真 界的 。

外,在我们 在 历的大 据时 , 为 据分 法的一个巨大分支,基 贝 的 器学习


法也在 广泛地 用,并产生很多 。 贝 法、贝 念 , 广泛地应用
分类和 。对 海量 据的 分类问题,例 , 件的 选和过滤,基 贝 法的 法取得
了非常好的效 ,并在很多 司中 在 用,帮助我们 件的 扰。

更 能可 的是, 用 对 的Python语 ,对 涉 的 例进 了编 。对 有一
基础的人来说,通过 ,可以进一步 贝 法的应用,真 握并 可以利用这 达到
一反三的效 。

用 的语 ,大量的 例和故事, 以 的Python语 , 原 燥的概率 讲得生动


。在学习到 的 时,还了 了 的真 以 可以 用的地 。对 有 的工 和
感兴 的读 ,这是一 自我的很好的图 。

酷我 
 雷鸣①

①雷鸣,现 酷我 事 、CEO,国家 人 聘专家, 度创始七 客 一, 度 发动 的


早期 和 术负责人 一。 北 大学 科学硕 学位和 福大学 学 MBA学位, 北
大学 学生会 和 福大学中国学生学 合会 。

前言

学习之道
这 以 Think 其他 籍的一个 是:只要 得编 ,你就能用这个 能去学习其他的内

大多 贝 统 的 用 学符 并以 学概念的形式 示 学 想, 微积分。 用
了Python 不是 学, 散近 不是 续 学。结 就是原 要积分的地 变成了 和,概率分
的大多 操 变成了 的 环。

我 为这 的 是 的,至少对 有编 的人们来说是这 的。 选择时也非常


用, 为我们可以选取最合 的 型 不用担心 常 分 太多。

外,这也 了一个 型到真 问题的平滑发展路线, 3章就是一个好示例。 由一个


骰子的 例子开始,那是基 概率的一个 题; 接着 到了一个我 Mosteller《50个挑 的统 学
题》(Fifty
Challenging
Problems
in
Probability)一 中 用的 问题;最后是德军 克问题,这个
界大 中成功的贝 法应用案例。

建模和 似
中多 章 的灵感都是由真 界里的问题 激发的, 以涉 了一 ,在应用贝
法( 其他的分 法) ,我们必须决 真 界中的 部分可以 进 型, 细 可
以 抽象 。

例 , 7章中那个 冰球 伍的例子,我 入球得分 为一个 松过 ,这 示着在


的 时段入球 会都是 的,这并不 符合 情况, 就大多 目的来说可能就 了。

12章中,问题是对SAT得分进 (SAT是用 美大学的入学 准 试)。我以一个 有


SAT试题 度 的 型开始, 其 SAT的试题 中既 了 对 ,也 了 对较 的试
题。 后 出了 个反 这一 目的的 型,结 显出 个 型在最 效 上没有大的差 。

我 为在 决问题的过 中, 过 为其中一部分是重要的, 为这会 醒我们 误


差(也就是 中 和 带来的误差)。

中的很多 法都基 散分 ,这让一 人担心 误差, 对 真 界的问题, 误差


来都小 误差。

, 散 法总能允许较好的 选择,我宁愿要一个近 的良好的 型也不要一个 却 糕


的 型。

一个 度看, 续 法常在 能上有优势, 能以常 时 杂度的 法 线 平


时 杂度的 法。

总的来说,我 荐这 步 的一个通用流 下。
1. 研究问题时,以一个 型开始,并以清晰、好 、 证无误的 现 。 集中
在好的 决 不是优 上。

2.一 型有效, 找到最大的 误来 。这可能 要 散近 过 中 的 量,


洛 法中的 , 型细 。

3. 对你的应用 能就 了,则没必要 优 。 要做,有 个 向可以 :


你的 以寻找优 ,例 , 你缓 了 的 结 ,你也许能 免重 冗余的 ;
可以去发现找到 捷径的分 法。

这一流 的好 是 一、 步较快, 以你能在 入大量 研究多个可 的 型。

一个好 是在 三步,你可以 一个大体 的可参 现开始进 归 试。也就是, 查优


后的 是 得到了 的结 ,至少是近 的结 。


中 的 很 多 例 子 用 了 在 thinkbayes.py 中 的 类 和 , 可 以
http://thinkbayes.com/thinkbayes.py下载这个 。

大多 章 了可以 http://thinkbayes.com下载的 ,其中有一 依 也 要下载,我


你 这 件 部 入 一个目 ,这 就可以 此 用 无 变更Python的库 件 路
径。

你可以在 要时 下载这 , 一 http://thinkbayes.com/thinkbayes_code.zip下载,这个


件也 了 用的 据 件, 压时, 创 为thinkbayes_code的 中 有 的
目 。

外 , 是 Git 用 户 , 你 可 以 通 过 fork 和 clone 来 一 得 这 个 仓 库 :


https://github.com/AllenDowney/ThinkBayes。

我用到的 一 是 thinkplot.py , 对 pyplot 中 一 进 了封 ,要 用 要 好


matplotlib, 还没有, 查你的软件 管 器看看 是 在, 则你可以 http://matplotlib.org得到
下载指南。

最后, 中一 用了NumPy和SciPy,可以 http://numpy.org和http://scipy.org
 得。

有 的 Python 会 到 中的 没 有 符 合 PEP
 8 这 一 最 通 用 的 Python 编 指南


(http://www.python.org/dev/peps/pep-0008/)。

切地说,PEP
8 用带有词 下 线的小写 like_this, 在 中和 现的 里, 和


法 以大写开 并 用 隔式的大小写,LikeThis。

没有 PEP
8 的原 是在我为 中内 准 时 在 歌做访问学 , 以就 了 歌的


编 , 只在少 地 沿袭了PEP
8,一用上了 歌风格我就 上了,现在要改太 。
,在 题风格上, 在“Bayes’s
theorem”中,s 在 后,在 风格指南中倾向这 用
在其他指南 中不是。我没有 的 好, 不得不选择其一, 以就是你们现在看到的这个。

最后一个 上的 脚是: 穿 ,我 用PMF和CDF 示概率密度 积分 这 学


概念, Pmf和Cdf是指我 的Python对象。

预备
还有 个出色的能在Python中进 贝 统 的 , pymc和OpenBUGS,由 读 要有
多的 景 能开始 用这 , 此 中我没有 用 们, 我想 读 的 条件最
小。 你了 Python和一点点概率 ,就可以开始 读 。

1章 概率 和贝 ,没有 。 2章 了Pmf,一望 是用来 示概率密度


(PMF)的Python字 对象。然后 3章我 了Suite,一个Pmf对象,也是一个能进 贝 更新的
架, 万事 了。

好了, 后的章 中,我 用了 ( 态)分 , 和 松分 ,beta分 分 型的概率


分 ,在 15章,我 了不太常 的狄利克雷分 ,不过接着也进 了 。 你不 悉这类分 ,
可以 维基 科了 们。也可以 读 的一 指南《统 维》(Think
Stats), 其他入门 的统
学 籍(不过, 怕大多 类 籍都会 取对 没有太大帮助的 学 法来 )。

中 用的惯 写
中 用了下 的印刷 例。

体(Italic)

示新术语,URL, 件地址, 件 和 件扩展 。

宽(Constant width)

用 ,也 那 示 元 的段 ,例 ,变量和 , 据库, 据类型,环


境变量, 和 键字。

宽粗体(Constant width bold)

命 其他由用户 入的 字。

宽 体(Constant width italic)

应 由用户 入 由上下 决 的 。

这个图 示这是一个 示、 一般 的 记。
这个图 示这是 醒 示。

我们的联 方式
你想就 发 有 问,敬请 出 社。

美国:

O’Reilly
Media
Inc.

1005
Gravenstein
Highway
North

Sebastopol,
CA
95472

中国:

北 西 西直门南大 2 成铭大 C 807室(100035)

奥 利 术咨询(北 )有 司

我们还为 创 了一个 ,其中 含了勘误 、示例和其他额外的 息。你可以通过地址访问


:http://oreil.ly/think-bayes。

的 术 问题 ,请发 件到:bookquestions@oreilly.com。

迎 我们的 站(http://www.oreilly.com),查看更多我们的 籍、 、会 和最新动态


息。

我们的其他 式 下。

Facebook:http://facebook.com/oreilly

Twitter:http://twitter.com/oreillymedia

YouTube:http://www.youtube.com/oreillymedia


你发现 有 要更 的地 其他 ,请发 子 件至downey@allendowney.com。一
根据你的反 进 了修 ,我会 你 入 (除了要 不 的情况)。

含 误 的段 部分,会让我更 找到 们。只 和 也可以, 还是不太 找


到 误 。这里先 !
 

首 先 , 我 要 感 大 · 麦 凯 ( David
 MacKay ) 的 优 秀 《 息 、 和学习 法》


(Information
Theory,
Inference,
and
Learning
Algorithms),我 这 里 一 了贝 法。
他允许我 用他 中的 个问题来 为例子。
这 也得 我和圣 恩· 哈的 互 合,2012的 天我在欧 学 审 了他的贝

在参 波 顿Python用户 项目时,我在 时 成了 的部分内 , 以我也要感 他们以
他们 的 。
纳 ·爱德华 交了 一个 写 误。
· 发现了一个 记 误。
奥利维 出了 个有 的 。
尤里· 西 克发现了 个 误。
克里 托 ·欧 交了一个更 和 的清 。
伯 · 库 发现了一个 误 的小写i。
麦克 ·黑 在 1章 一个 清章 。
库 · 勒指出“ 中有 的取出饼干”并不是一个真 的场景。
姆·波 德和 A.吉 纳 指出,在 案例中的 量有 问题。
兰姆· 发现了一个 写 误,还 了 清章 。
2013 天在我的《贝 统 》 上,学生们 出了许多有 的修 和 ,他们是:凯·奥
汀,克 ·巴 , 里· 德 ,瑞 ·铂 ,凯 ·门多 ,阿 · 耶, ·克 普,内 · ,
凯 ·麦克康诺亥, 历克·雷德福, 伦 ·里 , · 普 。
格雷 · 和 ·艾 帮我 清了“ 的 格”这个问题的一 讨 。
库 ·奥格伦指出 问题的原有 是有 含煳的。
O’Reilly
Media的 敏和 在 对 的过 中也发现了许多可改进的地 。


第1 
 贝 斯定理

1.1

有贝 统 的 法都基 贝 , 有条件概率的学习基础, 到这一点很自然。 此
我们会 概率、条件概率开始,然后到贝 ,最后讨 贝 统 的内 。

概率 示为0和1 的 字( 0和1),含 是 一事件 为的可 度,1 示“事件


为真”的情形 发生, 为 成真; 0 则 示“事件为真”这一情形为 。

其他中 示 的 度。例 ,0.5通常也会写成50%, 着一个 结 发生和不发生有


可能 。例 ,在一个 币事件中,人像 ( )朝上的概率就非常接近50%。

条件概率是带有 ( 条件) 景约束下的概率问题。例 ,我想了 一下 年自己心脏 发


的可能 。根据疾 控 中心的 据, 年 大 约 有 78.5 万 美国人罹患心脏
(http://www.cdc.gov//heartdisease/fact.html)。

美国约有3.11亿人, 挑选一个美国人,那么其在 年心脏 发 的概率大约是0.3%。

就 体个例 ,“我”可不是那个 选中的美国人。流 学家们 了多 心脏


发 的风 ,根据这 我的风 则有可能 平均 。

人男,45
岁,有 界 固醇,这 了我发 的可能 ;然 , 压 、不抽烟这


则降 了可能 。

上 这 条件 入在线 器http://hp2010.nhlbihin.net/atpiii/calculator.asp,我发现自己 年心脏


发 的风 约为0.2%, 国平均 平。这个 就是一个条件概率, 为 是基 一 的,
这 构成了我患心脏 的“条件”。

通常条件概率的记 是p(A|B), 示在给 B条件下A事件发生的概率。在这个例子中,A 示我 年


罹患心脏 带的概率, B 示了上 的条件。

1.2
 联
合概率:是指 个事件 时发生的概率。p(A和B)是A和B事件的发生都为真的概率。

你 了 骰例子和 的 景,我们开始学习下 的 式:

p(A和B)=
p(A)p(B)
 
 醒: 达式并非总是成 。

例 , 我 个 币,A 示 一枚 币 朝上,B 示 枚 币 朝上,那么p(A)=


p(B)
=
0.5, 的p(A和B)
=
p(A)p(B)
=
0.25。

是上 式 在A和B都是独 事件的情况下 成 。 : A事件的结 并不 改变B事件


发生的概率。 更 式 示为,p(B|A)=
p(B)。

一个事件 并不独 的例子。 
A
 示今天下雨的事件,B
 示 天会下雨的事件。


我 道今天下雨,则 天还有可能下雨(译 : 独 一天会下雨的概率 较),
以p(B|A)>p(B)。

通常 下, 合概率 为

p(A
and
B)
=
p(A)
p(B|A)

对 A、B事件, 一天下雨的 会是0.5, 续 天就不会是0.25, 是可能更 一点。

1.3
 曲奇
我们 开始讨 到贝 , 我还想通过一个 称为“ 饼问题”的例子来 。 有
饼, 1 含30个香草 饼和10个 克 饼, 2有上 饼干 20个。

现在 想你在不看的情况下 地挑一个 一 饼,得到了一 香草 饼。我们的问题是:


1取到香草 饼的概率是多少?

这就是一个条件概率问题;我们希望得到概率p( 1|香草), 怎 进 并非显 。问题


成在 1中香草 饼的概率则 得多。

p(香草| 1)=
3/4

不 的是,p(A|B)并不和p(B|A) , 有 法 一个 出 一个:贝 。

1.4
 贝 斯定理
现在,我们准 好进 贝 导 要的 有条件了。首先,我们 到, 合概率是 积可交
( 法交 )的, :

p(A
and
B)
=
p(B
and
A)

对 A,B 示的事件都成 。

然后,我们写出一个 合概率的 达式:

p(A
and
B)
=
p(A)p(B|A)

由 我们并没有 A和B的含 , 可以对A、B进 互 操 。

交 们的位 :

p(B
and
A)
=
p(B)p(A|B)

这 达式 接起来,我们得到下 的 达式:

p(B)p(A|B)=
p(A)p(B|A)

这 着我们有 式 合概率, p(A), 以p(B|A); 一 向, p(B), 以


p(A|B)。 法是 的。

最后, 上式除以p(B),得到:
这 是贝 !看起来不起眼,不过 会显示出 人吃惊的强大 。

例 ,我们可以用 来 决 饼问题。

B1 示 饼 1的概率,V 示 饼是香草 饼的概率。

带入贝 我们得到:

式 就是我们希望得到的,一 香草 饼来自 1的概率。

式的右 示:
 

p(B1):这是我们 略得到 饼这个条件时( 条件下)选中 1的概率。 为选择 的过 是


的,我们可以 p(B1)=1/2。
p(V|B1):这是 1得到一个香草 饼的概率=3/4。
p(V): 里得到一个香草 饼的概率。 为 到选择 的 会均 , 个 的 饼
量都是40,得到 饼的 会是 的。 个 中香草和 克 饼总 是50和
30, 此p(V)
=5/8。

们 在一起,我们得到:

结 是3/5。 以,“得到一 香草 饼”是支 “来自 1”的证据, 为香草 饼来自 1的


可能 更大。

这个例子 示了一个应用贝 的案例: 了一个 p(B|A)
得到p(A|B)的 略。

这 略在 决类 “ 饼问题”的情况下是有用的, 贝 式的右 要 的情
况下。

1.5
 历时
还有 外一 贝 的 路: 给我们 的是一 根据 据集D的内 变 更新 概率
H的 法。

这 对贝 的 称为“历时 ”。

“历时” 着 事情 着时 发生;在 例, 是 的概率 着看到的新 据 变 。

在 H和D的情况下,贝 的 达式可以改写成:
在这 里, 项 下:
 

p(H)称为先验 , 在得到新 据 一 的概率。


p(H
|D)称为后验 , 在看到新 据后,我们要 的 的概率。
p(D|H)是 下得到这一 据的概率,称为似然 。
p(D)是在 下得到这一 据的概率,称为标准 。

有 情况,我们可以基 现有 景 息进 。 在 饼问题中,我们就 选中 1 2
的概率 为均 。

在其他情况下,先 概率是 的;对 一先 概率, 派的人可能会有不 , 许由


他们 用不 的 景 息做出 断, 为他们 对 的 条件做出了不 的 读。

然度是贝 中最 的部分,在 饼问题中 饼来自来自 个 ,则我们就 那个


中香草 饼的概率。

准 常量则有 手, 为在 有的 条件下这一 据出现的概率, 为 的 是最


一般的情况, 以不 这个常量在 体应用场合的现 。

最常 的,我们可以指 一 下的 集来 。

的:集合中,至多一个 为真。

备的:集合中,至少一个 必为真, 集合 含了 有的 。

我 用suite这个词来 示 上 的 集。

在 饼问题中, 有 个 :饼干来自 1 2, 们就是互 的和 的。

在 例中,我们可以用 概率 式 p(D), 发生 一事件有互不 的 个可能 ,可以像下


这 概率:

p(D)
=
p(B1)p(D|B1)
+
p(B2)p(D|B2)

入饼干问题中的 ,得到:

p(D)
=
(1/2)(3/4)
+
(1/2)(1/2)
=
5/8

我们早 心 得到的结 也是一 的。

1.6
 M&M豆
M&M 是有 颜色的 克 。 M&M 的Mars 司会不时变更不 颜色 克
的 合 例。

1995年,他们 出了 色的M&M 。在此 一 普通的M&M 中,颜色的搭 为:30% 色,20%


黄色,20%红色,10% 色,10% 色,10%黄 色。这 后变成了:24% 色,20% 色,16% 色,
14%黄色,13%红色,13% 色。

我的一个朋 有 M&M ,他告诉我一 是1994年,一 是1996年。


他没告诉我 体 个 子是 一年的,他 个 子里 取了一个M&M 给我。一个是黄色,一
个是 色的。那么黄色 来自1994年的 子的概率是多少?

这个问题类 饼问题,只是变 了我抽取 的 式
( 还是 )。这个问题也给了我一个


会 示 法:也就在 在 上 就可以 决类 这 的问题(译 : 为后续章 的 型
法 垫)。在下一章中,我们 以 法 这 问题。

一步是枚 有 。取出黄色M&M 的 子称为 1, 一个称为 2, 以 是:


 

A: 1是1994年的, 2是1996年的。
B: 1是1996年的, 2是1994年的。

接着我们 一个 格, 示 个 , 示贝 中的 一项:

 先验 p(H )  似然 p(D|H )  p(H)
p(D|H )  后验 p(H|D )
  A   1/2   (20)
(20)   200   20/27 
  B   1/2   (10)
(14)   70   7/27 

一 示先 。基 问题的 ,选择p(A)=p(B)=
1/2是合 的。

示 然度, 了问题的 景 息。 例来说, A为真,黄色M&M是来自1994年的


概率20%, 色来自1996 的概率为20%。 为选择是独 的,我们 其 以得到 合概率。

三 由 得到。此 的总和270是归一 常 (译 :参 概率 式)。为了得到最后一


的后 概率,我们 三 的 归一 后得到 四 的 。

就是这 。 吧?

还有,你可能会 一个细 扰。我 p(D|H)写成了 分 的形式 不是概率形式,这 着 没


有除以 子10000。 是 我们 其除以归一 常 时就 消了, 此这不 结 。

的 是互 和穷 的,你可以 然度 以 子, 便, 一个 子应用到整
上。

1.7
 Monty
Hall
大 (Monty
Hall
problem) 题可能是历 上最有 的概率问题。问题看 ,
案 此有悖常 以 很多人不能接受,很多聪 人都 堪 自己搞 了反 据 , 是 开的。

大 是游戏 目“来做个交 ”(Let’s
Make
a
Deal)的 场。 大 题也是这一 目的常


游戏 一。 你参 目, 则是这 的:
 

向你示 三个 闭的大门,然后告诉你 个门后都有一个 :一个 是一 , 外 个是


像花生酱和 指甲这 不 的 。 。
游戏的目的是要猜 个门后有 。 你猜对了就可以 汽 。
你先挑选一扇门,我们 称 为门A,其他 个称为门B和门C。
在 开你选中的门 ,为了 悬念, 会先 开B C中一个没有 的门来 悬念( 汽
上就是在A门 后,那么 开门B 门C都是 的, 以他可以 选择一个)。
然后 给你一个选择。 最 的选择还是 到剩下的未 开的门上。

问题是,你应 “ ”还是“ ”?有没有 ?

大多 人都有强烈的直 , 为这没有 。剩下 个门没有 开, 在门A 后的 会是50%。

是,这是 的。事 上, 你 选择门A,中 概率只有1/3; 到 外一个门,你的


会 是2/3。

用贝 ,我们可以 这个问题分 成 个 部分,也许这 可以说服自 ,“ ”的 案


上的的 是对的。

首先,我们应 对 据进 细描 。在 例中为D 个部分: 开了门B, 没有 在


后 。

接下来,我们 了三个 :A,B和C, 示 在门A,门B, 门C后 。 , 用 格


法:

 先验 p(H )  似然 p(D|H )  p(H)
p(D|H )  后验 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 

填写先 很 , 为我们 告 是 的,这 可能在 门后 。

然度 要一 ,在充分合 的 后,我们 的 然度 下:
 

A: 汽 上是在门A后, 可以 地 开门B 门C。 以他选择门B的概率为


1/2。 为 上是在门A后,也就是说 不在门B后的概率是1。
B: 汽 上是在门B后, 不得不 开门C,这 他 开门B的概率就是0(译 :
也就是这个 的 然度为0,不可能发生)。
最后 C: 是在门C后, 开门B的概率为1,发现 不在那儿的概率为1(译 :
为在选手 选了A门这个情况下,可 悬念开门的选择只有B和C, C有 ,
不会选, 此 会 开B门的概率为1,也就是在这个 下, 据D的 然度为1)。

现在我们 成有 度的部分了,剩下无非就是 术。 三 的总和为1/2,除以后得到p(A|D)
=


1/3,p(C|D)
=
2/3, 以你最好是 个选择。

问题有许多变形。贝 法的优势 一就是可以 广到这 变形问题的 上。

例 , 想 总是 可能选择门B, 只有在 不得 的时 选门C( 在门B后)。在这


情况下,修 后的 下:

 先验 p(H )  似然 p(D|H )  p(H)
p(D|H )  后验 p(H|D )
  A   1/3   1   1/3   1/2 
  B   1/3   0   0   0 
  C   1/3   1   1/3   1/2 
唯一的变 是p(D|A)。 在门A后, 可以选择 开B C。 在这个变形问题里 ,他总是选
择B, 此p(D|A)
=
1。

此,对A和C, 然度是 的,后 也是 的:p(A|D)
=
p(C|D)
=
1/2,在这 情况下, 选


择B
门显示不了 位 的 息, 以无 选手选择 不变还是改变都无 要。

反过来的情况下, 开门C,我们就 道p(B|D)
=
1(译 : 为 总是优先选择门B,


门D是他 开了门C, 此在 在门B后的 下,他必然会 开门C,概率为1, p(B|D)=1)。

章中我 了 问题, 为我 得这里有 的 ,也 为贝 问题的 杂 更 控


。 这并不 是一个 型的贝 应用, 以 你 得 人 ,没什么好担心的!

1.8
 讨
对 涉 条件概率的很多问题,贝 了一个分 的 略。 p(A|B) 以 ,
以用 量,可以 查 贝 中的其他项是 更 , p(B|A),p(A)和p(B)。

大 问题让你 得有 ,我在一篇 章“All
your
Bayes
are
belong
to
us”中收集了很多类 问


题,你可以去 击链接进 读 http://allendowney.blogspot.com/2011/10/all-your-bayes-are-belong-to-
us.html。

第2 
 统

2.1
 分布
在统 上,分布是一 其对应的概率。

例 , 动一个 骰子,可能的 是 字1至6, 个 的概率是1/6。

一个例子,你应 有兴 了 在日常的 语 用中 个 词出现的 。你可以创 一个 含


个字 出现的 的分 。

为了 示Python中的分 ,可以 用一个字 射 个 和 的概率。我编写了一个 为Pmf 的类,


利用Python字 现了上 功能, 了一 有用的 法。为了对应 这 分 的 学
示法,我 其命 为Pmf。

Pmf 的 在 一 个 我 为 成 的 Python thinkbayes.py 中 。 可 以


http://thinkbayes.com/thinkbayes.py下载。 了 更多 息参 的“ 指南”。

要 用Pmf,可 下导入:
from thinkbayes.py  import  Pmf

下 的 创 一个Pmf来 示 骰子的结 分 :
pmf = Pmf() 
for x in [1,2,3,4,5,6]  :

    pmf.Set(x 1/6.0)

Pmf创 一个 的没有 的pmf。Set 法 个 的概率为1/6。

这里是 一个例子, 个 词在一个词 中出现的 :


pmf = Pmf()
for word in word_list:
    pmf.Incr(word, 1)

Incr为 个 词的 应“概率” 1。 一个词还没有出现在Pmf中,那么就 这个词 进去。

我 “概率” 上 是 为在这个例子中概率还没有归一 ,也就是说 们的 和不是1, 此不


是真 的概率。 在 例中 词 概率成 。 以 成了 有的 ,就可以通过除以 的总
来 得到概率。

Pmf 了一 Normalize 法来 现上 功能:


pmf.Normalize()

一 有一个Pmf对象,你可以像下 这 得到 一个 的概率:
print pmf.Prob('the')
这会 印 出 词“the”在词 中出现的 率。

Pmf 用Python字 来 储 其概率, 以Pmf中的 可以是 可 哈希的类型。概率可以是


类型, 通常是浮点 (float类型)。

2.2
 曲奇
在贝 的语境下,可以很自然地 用一个Pmf 射 个 和对应的概率。

在 饼问题里 , 是B1和B2。在Python中可以 用字符 来 示 们:

pmf = Pmf() 

pmf.Set('Bowl1' 0.5) 

pmf.Set('Bowl2' 0.5)

这一分 含了对 个 的先 概率,称为先验分布。

要更新基 新 据( 到一 香草 饼)后的分 ,我们 先 分 以对应的 然度。

1 到香草 饼的可能 是3/4, 2的可能 是1/2。


pmf.Mult('Bowl1' ,0.75) 
pmf.Mult('Bowl2' ,0.5)

你 愿,Mult 给 的概率 以 的 然度。

更新后的分 还没有归一 , 由 这 互 构成了 集合( 着 含了 有可能


),我们可以进 重新 一 下:
pmf.Normalize()

其结 是一个 含 个 的后 概率分 ,这就是 说的后验分布。

最后,我们可以得到 1的后 概率 下:
print pmf.Prob('Bowl 1')

案是0.6。你可以 http://thinkbayes.com/cookie.py下载这个例子。 了 更多 息,请参


的“ 指南”。

2.3
 贝 斯
在 续讨 其他的问题 ,我想在上一 的基础上重写 以 其更通用。首先我 一个类来封
此 的 
:
class Cookie(Pmf) : 
    def __init__(self,hypos)   :
        Pmf.__init__(self) 
        for hypo in hypos   :
            self.Set(hypo,1) 
        self.Normalize()
Cookie对象是一个 射 到概率的Pmf对象。__init__ 法给 个 的先 概率。 上
一 中就有 :

    hypos= ['Bowl1' 'Bowl2'] 
    pmf =Cookie(hypos)

Cookie类 了Update 法, 以data为参 并修 应的概率:


    def Update (self,data) :
        for hypo in self.Values()   :
            like= self.Likelihood(data,hypo) 

            self.Mult(hypo like) 
        self.Normalize()

Update 历suite中的 个 ,并 其概率 以 据在 一 下的 然度, 然度由Likelihood



   mixes = {
       'Bowl 1':dict(vanilla=0.75, chocolate=0.25),
       'Bowl 2':dict(vanilla=0.5, chocolate=0.5),
       }

   def Likelihood(self, data, hypo):
       mix = self.mixes[hypo]
       like = mix[data]
       return like

Likelihood 用mixes, 用Python的字 结构来 射 和在 中 饼的 合 例。

下 这 进 更新:
    pmf.Update('vanilla')

然后我们就可以 印 出 个 的后 概率:
    for hypo , prob in pmf.Items()   :

        print  hypo prob

其结 是
Bowl 1  0.6
Bowl 2  0.4

结 和我们 得到的结 一 。 起我们在 章 看到的,这段 更 杂。

一个优点是, 可以 广到 一个 取不只一个 饼(带 )的情形:


    dateset= ['vanilla', 'chocolate', 'vanilla'] 

    for data in dataset  
        pmf.Update(data)

一优点是, 了 决许多类 问题的 架。在下一 中,我们 决 大 问题的 ,然


后看看 架的 部分 。

中的 可以 http://thinkbayes.com/cookie2.py 得。 了 更多 息,请参 的“ 指
南”。
2.4
 Monty
Hall
为了 决 大 (Monty
Hall)问题,我 一个新的类:
class monty(Pmf) : 

    def __init__(self hypos)   :
        Pmf.__init__(self) 
        for hypo in hypos   :
            self.Set(hypo 1)  ,
        self.Normalize()

到目 为 , 大 和 饼是 一 的。创 Pmf的 也一 ,除了 的 称:


    hypos='ABC' 
    pmf =Monty(hypos)

对Update的调用 是 的:
    data='B' 
    pmf.Update(data)

Update的 现也是 一 的:

    def Update (self data)   :
        for hypo in self.Values ()   :
            like = self.Likelihood(data hypo) ,
            self.Mult(hypo,like) 
        self.Normalize()

唯一 要 额外工 的是Likelihood:
    def Likelihood (self,data,hypo) : 
        if hypo==data   :
            return 0 
        elif hypo=='A'   :
            return 0.5 

        else  
            return 1

最后, 印 出的结 是一 的:


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

案是
A 0.333333333333 
B 0.0 
Ç 0.666666666667

在 例中,Likelihood的编写有一点点 杂, 贝 架的Update很 。 中的 可以
http://thinkbayes.com/monty.py 得。 了 更多 息,请参 的“ 指南”。

2.5

现在,我们看看 架的 元 是 的,这 我们就可以 们封 进一个Suite对象, 一个
__init__,Update和Print 法的pmf对象:

class Suite(Pmf) 
    “代表一套假设及其概率。” 
    def __init__(self,hypo=tuple()): 
        “初始化分配。” 

    def Update(self,data): 
        “更新基于该数据的每个假设。” 

    def Print (self): 
        “打印出假设和它们的概率。”

Suite的 现在thinkbayes.py中。要 用Suite对象,你应 编写一个 承自Suite的类,并自


Likelihood 法的 现。例 ,这是一个以 大 问题改写的 用Suite的 案
:
from  thinkbayes  import Suite 
class Monty(Suite)  :
    def Likelihood (self,data,hypo) : 
        if hypo ==data  :
            return 0 
        elif hypo=='A'  :
            return 0.5 

        else  
            return 1

下 是一个 用这个类的 :
    suite=Monty('ABC') 
    suite.Update('B') 
    suite.Print()

你可以 http://thinkbayes.com/monty2.py下载这个例子。更多 息 的“ 指南”。

2.6
 M&M豆
我们可以 用Suite 架来 决M&M 的问题。除了编写Likelihood有点 手,其他一切都很 。

首先, 要对1995年 和 后的颜色 合情况进 封 :


mix94=dict(brown= 30 ,
           yellow= 20 ,
           red= 20 ,
           green= 10 ,
           orange= 10 ,
           tan= 10) 

    mix96=dict(blue= 24 ,
               green= 20 ,
               orange= 16 ,
               yellow= 14 ,
               red= 13 ,
               brown= 13)

然后,封 :

    hypoA =dict(bag1 = mix94 bag2 = mix96) 

    hypoB =dict(bag1 = mix96 bag2 = mix94)
hypoA 示 1是1994年, 2是1996年。hypoB是 反的 合。

接下来, 的 称来 射其含 :


hypotheses=dict(A=hypoA B=hypoB)

最后,开始编写Likelihood。在这 情况下, hypo是一个A B的字符 , 据是一个指 了 子


年 和颜色的元 。
  def Likelihood(self, data, hypo):
      bag, color = data
      mix = self.hypotheses[hypo][bag]
      like = mix[color]
      return like

下 是创 suite对象并进 更新的 :
    suite = M_and_M('AB')

    suite.Update(('bag1', 'yellow'))
    suite.Update(('bag2', 'green')) 

    suite.Print()

结 下:
A 0.740740740741 
B 0.259259259259

A的后 概率大约是20/27, 是我们 得到的。

中的 可以 http://thinkbayes.com/m_and_m.py 得。 了 更多 息,请参 的“ 指
南”。

2.7
 讨
章 了Suite类, 封 了贝 update 架。

Suite 是一个抽象类(abstract
type),这 着 了 Suite 应 有的接口, 并不 整的


现。Suite接口 Update和Likelihood 法, 只 了Update的 现, 没有Likelihood的 现。

具 类(concrerte
type)是 承自抽象父类的类, 了缺 法的 现。例 ,Monty扩展自


Suite, 以 承了Update并 现了Likelihood。

你 悉 式,你可能会 到这其 是 式中 法的一个例子。你可以


http://en.wikipedia.org/wiki/Template_method_pattern了 这个 式。

大多 在以下章 中的例子 的 式,对 个问题我们 一个扩展的Suite对象, 承了


Update法,并 了Likelihood。在少 情况下,会重写Update 法,通常是为了 能的缘故。

2.8
 习
练习2-1。
在 11 的“贝 架”里 ,我 到了 饼问题的 法是 的,是 饼有 充的取多个饼的
情况(有 的情况)。

更可能的情况是,我们吃 了取出的 饼,那么 然度就依 的取 饼 为( 饼少


了)。

修改 章中的 法以 没有 饼 充的情况。 示: Cookie 的 例变量来 示 的 状


态,并据此修改 然度。你可能要 一个Bowl对象。

第3 


3.1
 子
我有一盒骰子,里 有4 的骰子、6 的骰子、8 的骰子、12 的骰子和20 的骰子 1个。
玩过游戏《龙 地下 》,你 然会 白我的 指。

我 盒子中选一个骰子,转动 得到了6
。那么 一个骰子 选中的概率是多少?

我通过一个三步 略来 决这个问题。

1.选择 的 示 法。

2.选择 据的 示 法。

3.编写 然度 。

在 的例子中我用字符 来 示 和 据, 骰子问题中我 用 字。

切地说我 用整 4、6、8、12和20来 示 :
, ,8,12,20 ])
suite=Dice([ 4 6

外, 1到20的整 为 据。有了这 达式,编写 然 就很 了:


class Dice(Suite):
    def Likelihood(self, data, hypo):
        if hypo < data:
            return 0
        else:
            return 1.0/hypo

这里Likelihood的原 是: hypo<data, 着 骰子 大 骰子的 ,显然这是一个不可能的


情形, 以 然度是0。

外的情形下,问题变成“ 到 有 的点 ,得到 个点 结 的 会是多少?”

案是1/hypo无 据是什么。

下 是 用update( 转动得到6)的语 :
suite.Update (6)

后 分 的结 下:
4 0.0
6 0.392156862745
8 0.294117647059
12 0.196078431373
20 0.117647058824

得到6后,骰子是4 的概率是0。最可能的 选是6 骰, 也有约12%的可能是20 骰。


我们多 ,得到6,8,7,7,5,4这 一 据的情况下呢?

,,,,,
    for roll in [ 6 8 7 7 5 4 ]  :
        suite.Update (roll)

结合 据,可以去 6 骰的可能 了( 为有大 6的 ),8 骰看起来可能 很大。

结 下:
4 0.0
6 0.0
8 0.943248453672
12 0.0552061280613
20 0.0015454182665

现在有94%的可能我们转动了一个8 骰, 时还有1%可能是一个20 骰。

骰子问题参 了我在Sanjoy
Mahajan的贝 上看到的一个例子。

你可以 http://thinkbayes.com/dice.py下载 。 了 更多 息,请参 的“ 指南”。

3.2
 车头
我是在 雷德里克·莫 勒的《 十个概率 题的 法》(多 出 社,1987)一 中发现
问题的:

路上以1到N命 。有一天你看到一个 60的 ,请 路上有多少 ?

基 这一 察结 ,我们 道 路上有60个 更多的 。 这个 字到底是多少?

要应用贝 进 ,我们可以 这个问题分成 步 进 :

1.在得到 据 ,我们对N的 是什么?

2. 一个N的 后,得到 据(“ 志为60 的 ”)的 然度?

一个问题的 案就是问题的 概率。 个问题是 然度。

在选择 概率上,我们还没有太多的基 息, 我们可以 一 情况开始, 进一步的


法。 N可以是 1到1000 概率的 。
    hypos= xrange (1 ,1001)

接着我们 要的是一个 然 。先 在一个有N个 的 ,我们看到60 的概率


是多少? 只有一个 司( 只有一个我们 的 司),看到 一个 有 可
能,那么看到的 的 会为1/N。

然度 下:
class Train(Suite)  :

    def Likelihood(self data ,hypo) :
        if hypo<data :
            return 0
        else:
            return 1.0/hypo
看起来很 悉, 然 在 问题和骰子问题上是 的。

Update
 下:
    suite=Train (hypos)
    suite.Update (60)

为有太多的 (1000)要 印 出, 以我绘 了 图3-1 示的结 。 料 中的是,N中60以


下的 有 都 去 了。

图3-1
 问题的后 分 ,基 均 分 的先

非要猜 的 ,最可能的 是60。这 不上很好的结 , 竟,想想你恰好看到最 志


的 会是多少呢(应 不 吧)?不过, 想 猜到的 案 的可能 最大 ,你应 猜
60。

不过,这还不是我们的目 。 一个可选的 法是 后 概率的平均 分 :

def Mean(suite):
    total= 0
, :
   for hypo prob in suite.Items ()
        total + = hypo*prob
return total
print Mean(suite)

你可以用由Pmf 的非常类 的 法:
    print suite.Mean ()
后 的平均 是333, 以要是你想最大 度地减少 误,这也许是一个很好的猜 结 。

你一 一 地玩这个猜 游戏, 用后 概率的平均 来 为 会减少 来看的均


差(参 http://en.wikipedia.org/wiki/Minimum_mean_square_error)。

你可以 http://thinkbayes.com/train.py下载这个例子。 更多 息参 的“ 指南”。

3.3
 样看 先验 ?
为了进一步 决 问题,我们必须进 一 。

其中一 是 武断的。尤其 我们选择了在1-1000 的均 分 的先 概率。其 并没有


的 由选择1000 为上界 均 来 为分 征。

一个 着1000个 的 路 司 不上 , 一个 点的人可能会对这一问题做出更多
更少的猜 。

此,我们可能想 道是 后 概率分 对这 敏感。 依 一 察的小量 据,情况可能


真是 此的(敏感)。

一下, 1到1000的均 分 的先 概率,后 概率的平均 是333。 上界为500,我们得到


的后 平均 为207,一个2000的上界后 平均 为552。

以结 很 (猜 结 对上界敏感)。有 法 续进 分 :
 

取更多的 据。
更多的 景 息。

有了更多的 据后,基 不 的先 概率,后 分 收 。

例 , 除了 60我们也看到 30和90。我们可以这 更新分 :


, , :
    for data in[60 30 90]
        suite.Update (data)

用这 据时,后 概率的均 是

   

上限  后验 值 
   
500  152 
   
1000  164 
   
2000  171 

这 差异就较小了。

3.4
 他先验
没有更多的 据, 一个 法是通过收集 景 料优 先 。

大型和小型 司有 可能 的 也许 不合 ,大型 司可能有1000台 ,小型 司 有


1台 。

通过一 努 ,我们很有可能发现在 察 域内 司的清 , 可以 访 路 专家来


收集这 司一般 的 息。

是, 没有 入了 路产业的一 体情况,我们也可以做一 猜 。在大多 领域,有大量


小型 司,一 中型 司,一个到 个非常大型的 司。

事 上, 司 的分 往往 ,参 伯 ·阿克 在《科学》杂志上的报道
(http://www.sciencemag.org/content/293/5536/1818.full.pdf)。

这 , 少 10个 的 司有1000家,100个 的 司可能有100家,1000个


的 司有10家,10000个 的 司可能 有1家。

在 学上, 示 司的 量 司 成反 ,

其中PMF(x)是x的概率 量 ,α是一个通常接近 1的参 。

我们可以构 一个服 分 的先 下:
class Train (Dice) :
, ,
    def__init__ (self hypos alpha = 1.0) :
        Pmf.__init__ (self)
        for hypo in hypos :

            self.Set (hypo hypo** (-alpha))
        self.Normalize ()

下 是生成 概率的 :
    hypos=range(1,1001)
    suite=Train(hypos)

说 ,上 是 的, 对 分 的先 概率,后 概率对这一选择的敏感 较小。

图3-2 示了基 后 基 均 后 概率的 较。


图3-2
 为 的后 分 ,对 均 分

了 分 为 景 料后。我们可以消除大 700的N 了。

基 这 先 概率,在 察到 30、60和90时,后 概率分 是:



   

上限  后验 值 
   
500  131 
   
1000  133 
   
2000  134 

现在的差异小得多了( 不 上界的 )。事 上, 一个 大的上界,平均 都收


134。

以基 分 的先 概率是 较现 的, 为 基 司 的一般情况,并 在 中 现得
更好。

你可以 http://thinkbayes.com/train3.py下载 的例子。 了 更多 息,请参 的“ 指


南”。

3.5
 置信区间
一 出的后 分 ,通过 点 对后 分 进 总结通常是有用的。
对 点 ,通常 用平均 、中位 最大 然 。

对 ,我们通常给出 个 , 得未 量有90%的可能 入这 个 ( 其他的


概率 )。这 了一个置信区间。

的一个 法是在后 概率分 中 其中的概率,并记 对应 概率5%和95%的


。也就是说, 5和 95 分位。

thinkbayes 了一个 分位 :
def Percentile(pmf, percentage):
    p = percentage / 100.0
    total = 0
    for val, prob in pmf.Items():
        total += prob
        if total >= p:
            return val

下 是一个其应用 :
    interval = Percentile(suite, 5), Percentile(suite, 95)
    print interval

在 的示例(看到了三个 , 呈 分 的先 概率的 问题)中90% 为


(91,243)。 此大的 围其 切的 ,( 管平均 收 了)我们 然 不 究竟有多少
在。

3.6
 分布
在上一 中,我们通过 出 分 和Pmf的概率。 我们 要 多个 分位 ,更有
效 法是 用 积分 , Cdf。

由 含有 个分 的 的 息,在这个 上Cdf和Pmf是 的,并可以 时 一个转 到


一个。Cdf的优点是可以更有效地 分位 。

thinkbayes有一个 示 积分 的Cdf类。Pmf 了一 法生成 应的Cdf:


cdf = suite.MakeCdf ()

Cdf 了一个 为Percentile的


interval = cdf.Percentile(5), cdf.Percentile(95)

Pmf转 为Cdf 要 量len(pmf)的 时 。Cdf 和概率 储在有 里(list),


以查询 个概率得到 应的 要“对 时 (log
time)”: ,时 和 的 量的对 成 。查询
一个 得对应的概率也是对 时 , 以Cdf对 很多 来说都是有效的。

中的例子位 http://thinkbayes.com/train3.py。 了 更多 息参 的“ 指南”。

3.7
 德军 克
界大 期 ,在伦敦的美国大 部门 用统 分 来 德国生产的 克和其他
①。

西 军 得了一 记 簿,记 了 货和修 记 ,其中 克的底盘和发动 的 。


记 的分 , 为 克类型分 了以100为一个 的 , 个 内的 都是
成 的, 并不是 个 内的 字都用到了。 此一来,在 个100的 内, 德军 克问题的
围就可以 的 问题来缩小了。

基 这 ,美国和 国的分 们 成了 小 自情报部门其他形式情报的 结 。 在


后,记 显示这 结 上更准 。

他们也对 、 、 进 类 的分 ,产生准 用的 情报。

德军 克问题是个历 上有 的问题,也是一个很好的在现 界应用统 的例子。到目 为


, 的许多例子都是游戏 的问题, 我们 上会开始开始 决 问题。我 为 是贝 分
的优点, 是在我们 在 用的 法上, 了一条 基础 到研究 沿的捷径。

3.8
 讨
贝 中,有 径选择先 分 。一 人 选择最能 问题 景 料的先 概率,在
这 情况下,先 为是“信 ”。问题是,人们可能会 用不 的 景 息( 进 不 的 )。
以基 息的先 往往显得 。

一 法是 的“无信 参考的先验”,其目的是为了让 据来说 ,越没有约束越好。在 情


况下,你可以选择 含一 期望 的 殊先 ,例 ,就 量 一个最小先 。

“无 息先 ” 点 在是 为 们 更为客 。 通常,我倾向 用先 息。为什么呢?首先,


贝 分 总是基 型决 的。选择先 就是决 一, 不是唯一的部分,甚至可能不是最
的。 此, 无 息先 较为客 ,整个分 然是 的。

外,对 大多 中的问题,你很可能是在 个(对 ) :也许有大量的 据,也许没


有。 你有大量的 据,先 的选择不是 键; 息先 和无 息先 会得到 的结 。我
们会在下一章看到类 的例子。

不过, 像 问题, 你没有太多的参 据,那么 用 的 景 息( 分 )就有


很大 了。

德军 克问题, 必须基 你的结 做出生 的决 ,你就应 利用 有的 息, 不


是在“要 客 “的幻 中 不了 体情况。

3.9
 习
练习3-1。

为 问题写一个 然 ,我们必须要 这个问题:“ 路上有N个 ,我们看到60


的概率是多少?”

案取决 我们 察到 时, 用的取 过 。
在 章中,我通过指 只有一个 司( 只有一个我们 心) 决了这个 可的问题。

是 有很多家 用不 编 的 司, 看到 司 的 的可能
。在这 情况下, 然 是不 的, 为你更有可能看到一 由大型 司 的 。

为练习, 现 然 的这 变 ,并 较结 。

① 格 , . 证 法 情报大 [J].
《美国统 协会》杂志,1947,卷42, 237 。



第4 


4.1

在《 息 : 和学习 法》一 中,大 ·麦凯 出了这 一个问题:

2000年1月4日,星期 ,《 报》上 载了一个统 的 :

以 缘转动 利时一欧元 币250 后,得到的结 是 140 反 110 。“这看起来很可


”,伦敦 学 的统 讲 巴里· 说,“ 币是均 的,得到这个结 的可能
7%。”

那么,这一结 是 对‘ 币 心 非均 ’ 了证据呢?

我们 取以下 个步 这个问题。 一是 币 朝上的概率。 是 据是


支 了 币 心的 。

你可以 http://thinkbayes.com/euro.py下载 。 了 更多 息,请参 的“ 指南”。

以 缘旋转 一 币时都有 朝上的概率x。有 由 x的 取决 币的一 物 , 要是


重量的分 。

币 均 ,我们 x应 接近50%, 对 一个不 称的 币,x应 会大有差 。我们可


以用贝 和 到的 据来 x。

我们 一个 101,其中Hx 是 朝上的概率x%,其 0到100。首先以均 概率开


始,其中Hx的概率对 有的x是 的。后 我们 其他先 概率的情况。

likelihood 对 : Hx为真, 向上的概率为x/100 反 向上的概率为1−x
/
100。

class Euro(Suite) :

    def likelihood (self data hypo) , :
        x =hypo
        if data== 'H' :
            return x/100.0
        else :
            return 1 - x/100.0

下 是 现suite和update的 :
    suite=Euro (xrange (0   101)),
    dataset = 'H' * 140 + 'T' * 110

    for data in dataset :
        suite.Update (data)

其结 图4-1 示。
图4-1
 为均 分 的 下,欧元问题的后 分

4.2
 后验 的 述
总结一下,有 式来概 后 分 的 征。一 选择是找到后 分 的最大 然 。

thinkbayes 了一个 现:

def MaximumLikelihood(pmf) 
返回具有最高概率的值。
    “ ”
, ,
    prob val = max((prob  val)for val,prob in  pmf.Items ())
    return val

在这 情况下,结 是56,这也是 察得到的 分 140/250=
56%。 此这 地 了 察到的


分 就是最大 然 。

我们也可以 平均 和中位 来概 后 概率:


  print 'Mean', suite.Mean()
  print 'Median', thinkbayes.Percentile(suite, 50)

均 为55.95,中位 为56。
最后,我们可以 出一个 :
  print 'CI', thinkbayes.CredibleInterval(Suite, 90)

其结 是(51,61)。

现在, 到原来的问题,我们想 道 币是 是均 的。 察到的后 可 不 50%,这就


了 币的 是不均 的。

切地说,这不是开始的那个问题。Mckay 出的是“这 据是 恰恰为—— 币 心 非均


——给出了证据?要 这个问题,我们要更 地 “ 据为 一 说 了证据”这 的含 。不
过那是下一章的 题了。

那么,在 续探讨 ,我想先讲讲导 扰的原 。既然我们要 道 币是 均 ,很自然是 得


x为50%的概率:
  print  suite.Prob (50)

结 是0.021, 说 不了什么。这 得对 101的 显得毫无 。我们可 围


分成更多 更少的细小 , 这 ,对给 的概率则会更大 更小。

4.3
 先验 的 没
章开始,我们 先 是均 的, 这可能不是一个好选择。 币是 心的,可以 x会大
幅 50%, 心到 得x是10% 90%就太不可能了。

更合 的是选择在
50%附近有较 概率, 在那 端 上(指
10% 90%)概率较 的一个先 。

为一个例子,我构 了一个三 形状的先 概率, 图4-2 示。


图4-2
 欧元问题的均 型和三 型分 先

下 的 构成了 三 状的先 :


def TrianglePrior () 
    suite = Euro()

    for x in range(0   51) :

        suite.Set (x x)

    for x in range(51   101)  :

        suite.Set (x  100 - x)
    suite.Normalize ()

图4-2显示了结 (和均 先 概率 较)。以 的 据集更新先 概率得到 图4-3 示的后 分


。 上不 的先 ,后 分 也非常 。中位 和 是 的,均 差小 0.5%。
图4-3
 欧元问题的后 分

这就是先验 没的一个例子: 有 的 据, 在先 分 上 有不 点,人们也会得到


收 的后 概率。

4.4
 优
到目 为 ,我 展示的 都是为了 便 , 效率不 。通常,我先开发 证无误的 ,
然后 查对 达到目的是 快。 是, 就没有进 优 的必要。

在这个例子中, 我们 时 ,有 法可以 速 。

一个可能 法是减少归一 suite的 。在原始 中 一 真(转动 币)都调用 Update 一



dataset = 'H' * heads + 'T' * tails

for data in dataset:
    suite.Update(data)

下 是Update 法:
def Update(self, data):
    for hypo in self.Values():
        like = self.Likelihood(data, hypo)
        self.Mult(hypo, like)
    return self.Normalize()

Update都会 集,然后调用Normalize, 集。我们可以通过在Normalize


先update来 省一 时 。

suite 了一个 为UpdateSet的 法就是这么 现的, 下:


    def UpdateSet(self, dataset):
        for data in dataset:
            for hypo in self.Values():
                like = self.Likelihood(data, hypo)
                self.Mult(hypo, like)
        return self.Normalize()

下 是我们怎么调用 :
    dataset = 'H' * heads + 'T' * tails
    suite.UpdateSet(dataset)

这优 了速度, 时 是 据量成 的。我们可以通过改写
Likelihood 整个 据集,


不是一 真 一 。

在最 的 中, 据编写为 反 的字符 :
    def Likelihood(self, data, hypo):
        x = hypo / 100.0
        if data == 'H':
            return x
        else:
            return 1-x

有一 法,我们可以 据集 有 个整 的元 来进 编 : 和反 的 量。

在这 情况下的Likelihood 下:
    def Likelihood(self, data, hypo):
        x = hypo / 100.0
        heads, tails = data
        like = x**heads * (1-x)**tails
        return like

然后我们就可以像下 这 调用Update:
    heads, tails = 140, 110
    suite.Update((heads, tails))

由 我们用指 取 了重 的 法,对 不 量的 真(转动 币),这个 消耗


的 时 是一 的。

4.5
 Beta分布
还有一个进一步的优 让 法更快。

到目 为 ,我们 用了Pmf对象来 示一 散的x 。现在,我们 用一个 续分 ,


切地说是beta分 ( http://en.wikipedia.org/wiki/Beta_distribution)。
beta分 在 0到1( )的 上, 以 是一个描 例和概率的自然选择。稍 ,还
要更好。

你像上 一 ,用一个 项式 然 来 现贝 更新, 上beta分 是一个共 先验。那就


着 x的先 概率的分 是一个beta分 ,那其后 概率也是一个beta分 。 急, 这还要好。

beta分 的形状取决 个参 ,写为α和β, alpha和beta。 先 概率是带有参 alpha和beta


的beta分 ,我们看到h 和t 反 的 据,后 概率就是参 为alpha+h和beta+t的beta分 。
说,通过 个 法 现了Update 法。

以这很了不起,只不过 用 先 概率的分 的 是一个beta分 的情形。 的是,在最


度上,对许多 的先 分 beta分 都可以进 良好的近 , 时也可以 美匹 均 。参
alpha=1和beta=1的beta分 就是 0到1的均 分 。

让我们看看 利用这一切优势。thinkbayes.py 了一个类来 示beta分 :


class Beta(object):

    def __init__(self, alpha=1, beta=1):
        self.alpha = alpha
        self.beta = beta

默 情况下的__init__ 用均 分 。Update进 贝 更新:


    def Update(self, data):
        heads, tails = data
        self.alpha += heads
        self.beta += tails

data是一对 和反 量的整 。

此,我们有 一 法来 决欧元问题:
    beta = thinkbayes.Beta()
    beta.Update((140, 110))
    print beta.Mean()

beta 了Mean, alpha和beta的一个 :


    def Mean(self):
        return float(self.alpha) / (self.alpha + self.beta)

对 欧元问题后 的平均 为56%,这和我们 用Pmf得到的结 是 。

beta还 了EvalPdf, beta分 的概率密度 (PDF):


    def EvalPdf(self, x):
        return x**(self.alpha-1) * (1-x)**(self.beta-1)

最后,beta MakePmf 法, 用EvalPdf生成beta分 的 散近 。

4.6
 讨
在 章中,我们用 个不 的先 一个问题,发现在较大 据集的条件下,先 的
掩 了。 个人开始 对 先 有不 ,他们通常会发现, 着得到更多的 据,后 分 收
了。在一 点上,分 的差异 小到没有 。

这 情况出现时,会减 一 我在 一章 客 的担 。甚至对 许多现 界的问题, 显


不 的先 念最 都会 据 。

事 并非总是 此。首先,请记住, 有的贝 分 是基 型决 的。 你和我没有选择


的 型,我们可能对 据进 不 的 读( )。 此, 用 的 据,我们也会 得到不
的 然度, 后 概率就可能不收 。

外,请 ,在贝 Update中,我们以一个 然度 以 个先 概率, 以 p(H)为0,p(H|D)


也为0, 不 D是什么。在欧元问题上, 你 x小 50%, 指 其他 有 的概率为0,那么
多的的 据都 无法说服你。

这 看法是克 尔 则的基础, 是:应 免 一个 的先 概率为0, 怕的


在这 可能 ( http://en.wikipedia.org/wiki/Cromwell’s_rule)。

克伦威 法则以奥利 ·克伦威 命 ,他写下了“我 你,看在基 的 上, 为这可能是你是误


会了”。对 贝 法,这也是个好 ( 有点过度重 了)。

4.7
 习
练习4-1。

不是直接 察 币, 是 用一个不总是 的工 来 量结 。 体地说, 有一个概率


y 报告为反 , 报告 反 为 。

编写一个类来 这 一 给 了结 的 币的 量和 y,后 分 的 围是怎 依 y的?

练习4-2。

这项练习受到Reddit上一个帖子的 发,一位 dominosci的“redditor”在Reddit的统 小 上 出了


这个问题。http://reddit.com/r/statistics。

Reddit是一个在线 ,有许多 称为的subreddits的兴 小 。用户 称为redditors,redditor会贴上


上内 和其他 的链接。其他redditors对此链接进 决,对 量的链接给 “upvote”,不好
是不 的链接则给 “downvote”。

Dominosci 出了这 一个问题,就是redditor 中一 人 一 人更可 , 是Reddit并没有


到这个 。

我们的挑 是 一个 统, redditor做了 票,可以根据redditor的可 度 并 更新链接的


量, 对 redditor的可 度 也会依据这一链接的 量 更新。

一 法是 链接的 量以 得upvote的概率 ,redditor的可 度以对 条目给出 upvote


的概率 。

编写一个类来 redditors和链接,只要redditor 了票,update 对这 个对象进 更新。



第5 
 和加

5.1

示概率的 法 一是用0和1 的 字,不过这并非唯一的 法。 你玩过 球博 ,可
能 到概率的 一 示,称为 (odds) 。

你应 说过例 “ 率是三 一”这 的 , 也许不 道含 。 率是一个事件可能发生的概率


不发生的概率的 。

以, 为我的球 有75%的 会 ,我会说他们的 率是三 一, 为 的 会三倍


的 会。

你可以 率写成十进 形式, 最常 的是 其写成整 。 此“三 一” 写成3:1。

概率较 ,通常称为 (odds
against), 不是 (odds
in
favor)。例 , 得我的


只有10% 的 会,我会说赔率是9:1。

概率和 率是 息的不 示形式。给 一个概率,你可以这 率:


def Odds(p):
    return p / (1-p)

给 (支 ) 率的十进 形式,可以这 其转 为概率:


def Probability(o):
    return o / (o+1)

你以分子和分 示 率,可以像下 这 进 概率转 :


def Probability2(yes, no):
    return yes / (yes + no)

带着 率 维工 时,我发现 有助 人们的 点。 20%的人 为我的 ,那么其余


80%的人 然就 反, 赞成赔率是20:80 1:4
。

我的 的反向赔率是5:1,那么就是 分 的人 为 会 , 以 的概率是1/6。

5.2
 贝 斯定理的 形式
在 1章我写出了贝 的概率形式:

我们有A和B 个 ,我们可以写出后 概率的 下:


请 式中出现的 准 常 p
(D)
。

A和B是互 穷 的,就 着p(B)
=
1−p
(A), 此我们可以 先 的 率、后 的 率重写


为 率。 支 A的可能 写为o(A),得到:

在字 形式上,这说 了后 赔率是先 率 以 然 。 这 是贝 的 率形式。

这 形式 合在 上 脑海中进 贝 。

例 ,我们 到 饼问题:

有 饼。 1 含30个香草 饼和10个 克 饼。 2 含 饼 20个。

现在 你 选择了一个 ,然后 选择一个 饼。 是香草 饼, 来自 1的概


率是多少?

先 概率是50%, 以 率是1:1, 就是1。 然度是 , 3/2。 以后 概率就是3:2,对应 概


率3/5。

5.3
 的血
下 是来自麦凯的《 息 、 和学习》的 一个问题。

在一个犯罪现场,有 人遗 了 迹。一 犯奥利 过 试发现是“O”型 。 发现的痕迹


中 型分 是“O”型(一 地人口的常 型,有60%的概率)和“AB”型(一 的 型,概率
1%)。

那么这 据[现场发现的痕迹]是 支 奥利 是 犯 一[在现场遗 下 液证据的人]?

要 这个问题,我们 要想想“ 据支 了 ”这到底 着什么。直 上, 一


着 据的出现 呈现更大可能 ,我们就说“ 据支 了 ”。

在 饼问题上,先 率是1:1, 概率50%。后 率是3:2, 概率60%。 此,我们可以


说,香草 饼这一 据 为证据支 其来自 1的 
。

贝 的 率形式 了一 法, 这 直 更准 。

顾一下 式

除以o(A):

式 是后 率和 率的 。右 是 然 ,也称为贝 斯因子。
贝 子的 大 1,则 着 据更可能支 A 不是 B,也 着 更大,
率 也大 1, 着 着 据的出现 率也 了。

贝 子小 1,就 着 据支 B的可能大 支 可能A, 以支 A的 率降 了。

最后, 贝 子恰好为1时, 据 说有 可能, 以 率不会改变。

现在我们可以 到奥利 迹问题了。 奥利 是在犯罪现场 下 迹的人 一,就 了那


个“O”型 证据 的由来, 此 据的概率就是在人群中 挑中一个“AB” 型人的概率1%。②

奥利 没有在现场 下 液,我们就要对这 个 进 。 在人群中 选 人,有多大


可能 好找到一个“O” 型人和一个“AB” 型人?嗯, 可能情况: 一个人是“O”型 个
是“AB”型, 反过来 合一下。 以总的概率是2
(0.6)(0.01)
=
1.2%。

不是奥利 的 液, 据的 然度还要稍 , 以 液证据这个 据 上没有支 奥利 的


犯罪 。

这个例子有刻 的成分, 是一个 反我们自 的、符合 的 据却并非必然支 的例


子。

这一结 此有悖常 甚至 扰到你,下 的 路可能有 帮助: 据由一个常 事件


——“O”型 ,和一个 事件
——“AB”型 构成。 奥利 常 事件 (O型 ),这 得
的事件还是无法 。 奥利 常 事件无 ,那么我们有 可能找到“AB”型 的 犯。 情
况中的这一 导 了差 。

5.4
 加
贝 统 的基 操 是Update,这 要先 概率和一 据,并产生一个后 分 。 是, 决
问题通常涉 许多其他操 , 缩 、 法和其他 术 、最大 和最小 ,还有 合 。

章 法和最大 ;在 要的时 我会 其他的 。

一个例子基 《龙 地下 》这个 色 游戏,在这个游戏里,玩家决 的结 是通过 骰子来


成的。

事 上,游戏开始 ,通过转动3个6 骰子并 结 得到一个总和,玩家创 了自己 色的 个


) 量、 、 、灵 、体 和 。

以,你应 会对总和的分 感兴 。有 法可以 。

真:

给 一个 示骰子 分 的Pmf,可以绘 , 们 起来, 真 和的分 。

枚 :

给 个Pmfs,可以枚 有可能的 对,并 和的分 。

thinkbayes 这 个 。下 是 一个 法的 现。首先,我 一个类来 示 个骰子:


class Die(thinkbayes.Pmf):

     def __init__(self, sides):
         thinkbayes.Pmf.__init__(self)
         for x in xrange(1, sides+1):
             self.Set(x, 1)
         self.Normalize()

现在,可以创 一个6 骰子:


d6 = Die(6)

然后 用thinkbayes.SampleSum产生1000 转动3个骰子的 。
dice = [d6] * 3
three = thinkbayes.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,也在thinkbayes.py中:
def RandomSum(dists):
    total = sum(dist.Random() for dist in dists)
    return total

RandomSum在 个分 中调用Random然后 总其结 。

真的缺点是得到的结 只是近 的, 着n变大,结 会更准 , 是 时 也 了。

一 法是枚 有成对的 ,并 对的概率和总和。这在Pmf.__add__上 现:


# class Pmf

     def __add__(self, other):
         pmf = Pmf()
         for v1, p1 in self.Items():
             for v2, p2 in other.Items():
                 pmf.Incr(v1+v2, p1*p2)
         return pmf

self是一个Pmf对象,other可以是Pmf 其他 条目的对象。其结 是一个新的Pmf对象。


__add__的时 取决 self和other对象中的条目的 量, len(self)*len(other)。

下 是 用 :
    three_exact = d6 + d6 + d6

在Pmf中应用+操 符时,Python调用__add__。在这个例子中,__add__ 调用了 。

图5-1显示了通过 真生成的近 结 和枚 产生的 切结 。


图5-1
 转动3个6 骰子总和 的近 和 切分

Pmf.__add__是基
这 的 ,来自 个Pmf的 选择是独 的。在 多个骰子的例子中,这个
不 。其他情况下我们则必须扩展这个 法以 用条件概率。

中的 可以 http://thinkbayes.com/dungeons.py 得。更多 息请参 的“ 指南”。

5.5
 最大
你生成一个《龙 地下 》的 色,会对人物的最佳 有兴 , 以你可能想 道 分
的最大 。

有三 法来 一个最大 的分 。

真:

给 一个Pmf, 一选择的分 ,可以生成 ,找到最大 和 真最大 的 积分 。

枚 :

给 个Pmf,可以枚 有可能的 对,并 分 的最大 。

指 :
我们 一个Pmf转 为Cdf,有一个 有效的 法查找最大的Cdf(看后 )。

真最大 的 真 和的 :
def RandomMax(dists):
    total = max(dist.Random() for dist in dists)
    return total
def SampleMax(dists, n):
    pmf = MakePmfFromList(RandomMax(dists) for i in xrange(n))
    return pmf

我 做的只是用“max” “sum”。 对 枚 部分 是 的:
def PmfMax(pmf1, pmf2):
    res = thinkbayes.Pmf()
    for v1, p1 in pmf1.Items():
        for v2, p2 in pmf2.Items():
            res.Incr(max(v1, v2), p1*p2)
    return res

事 上,你可以 操 符 为参 来一般 这个 。

这一 法的唯一问题是, 个Pmf 有m个 , 时 m2。 我们想 道k个选择的最


大 , 要的时 km2。

我们转 Pmfs到Cdfs,我们可以以更快的速度进 的 ! 键是要记住 积分 的


其中X是一个 变量, 的 是“ 分 中 选取的一个 ”, 以 例来说,CDF(5) 示 分


中 个 是小 5的概率。

我 CDF1 中取出X, CDF2 中取出Y, 最大Z=max(X,Y),则Z小 5的可能 是多


少? 然,在这个案例里 ,X和Y必须小 5。

选择X和Y是独 为,

其中CDF3是Z的分 。我选择了5这个 让 式 读, 我们可以一般 为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
Max法接受选取的 k,然后 一个新的 示进 k 选择最大 的Cdf。此 法的 时
Cdf中的条目个 m。

Pmf.Max和Pmfs 现 的功能。只是 Pmf转 到Cdf必须要多做一点工 , 以 时 成


mlogm, 是这 然要好过 呈平 杂度的 时 。

最后,这里有一个 色的最佳 的分 的 例:
    best_attr_cdf = three_exact.Max (6)
    best_attr_pmf = best_attr_cdf.MakePmf ()

其中three_exact是上一 过的。 我们 印出结 , 看到产生一个有18 的 色的概


率大约是3%。

图5-2显示了分 。

图5-2
 转动3个6 骰子的最大 分

5.6
 分布
让我们 一个来自《龙 地下 》的例子。 我有一盒骰子,清 下:
5 个   4 面骰子
4 个   6 面骰子
3 个   8 面骰子
2 个  12 面骰子
1 个  20 面骰子

盒子中选择一个骰子转动,结 会呈现什么分 呢?

你 道选到的是 个骰子, 案很 。n 的骰子产生一个均 的 1到n的分 , 1和n。

是, 我们不 道选到的究竟是 个骰子,由此产生的分 则是有不 上界的均 分 的 分


布。

在一般情况下,这类 合量不 合 的 学 型, 可以 对PMF的直接 得到。

往常一 ,一个选择是 真,生成一个 真 的PMF。这 法很 , 会快速


得到一个近 的结 。 是, 想要 切的 法,我们 要一 不 的 法。

让我们 只有 个骰子的 开始,一个6 骰和一个8 骰。我们可以用Pmf来 示 个骰子:


d6 =Die(6)
d8 =Die (8)

然后我们创 一个Pmf 示这一 合分 :


mix = thinkbayes.Pmf()
for die in [d6, d8]:
    for outcome, prob in die.Items():
        mix.Incr(outcome, prob)
mix.Normalize()

一个 环枚 骰子, 个 环枚 环骰子结 和概率。在 环内部,Pmf.Incr 总了 个分


的 。

此 选中 个骰子是 可能的。更一般地,我们 要 道选中 一个骰子的概率,以便可以


对结 进 对应的 。

首先,我们创 一个 射了骰子和骰子 选中概率的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 pmf_dice.Items():
        for outcome, prob in die.Items():
            mix.Incr(outcome, weight*prob)

现在 个骰子都有 的 重了( 着骰子有了 )。

个结 到 合分 中,其概率 以 重,得到了图5-3 示的结 。 期的那 ,1至


4是最有可能的, 为 一个骰子都可以生成这 。12以上的 可能 不大, 为只有一个20 骰子能
有大 12的 ( 是20 骰子,要产生这 的可能 也都不到一 )。

图5-3
 盒子中 选中骰子的结 分

thinkbayes 了一个 为MakeMixture的 , 封 了 法的功能, 以我们 过 写成:


    mix = thinkbayes.MakeMixture (pmf_dice)

我们 在 7章和 8章 用MakeMixture。

5.7
 讨
除了贝 的赔率形式,这一章不是专门 贝 的。 贝 分 的一切都和分 有 ,
以了 分 的概念很重要。以 的 点来看,分 就是可以 示 一 (一个 过 的可能结
)和其概率的 据结构。

我们 看到了分 的 示形式:Pmfs和Cdfs。在 含了 息这一点上, 们是 的,这


你就可以 一个转 到 一个。 们 的 要 在 能:有 用Pmf更快、更 , 一
则是 用Cdf更快。
章 的 一 个 目 是 入 一 概 率 分 操 , 像 Pmf.__add__ , Cdf.Max 和
thinkbayes.MakeMixture。后续我们 用这 , 这里,我 的目的是 大家 分 为概率
的基 进 入 , 不 是 其 一个 和概率的 器。

①译 :odds 常 直 不严谨地称为赔率(这 博 业有 ,博 业就 一事件的赔率严格说是大


1的, 则不赚 ),事 上odds是 会的 。

②译 :记住 据 个 ,O型 和AB型 的现场证据。



第6 
 决 分

6.1
 “ 确的 ”
2007年11月1日,选手 希 和纳 参 《 的 格》这个美国 游戏 目。他们在 为
showcase的游戏环 中 ,游戏 题是猜展示 的 格。猜 到最接近展示 格的选手 得

纳 先开始。他的展 里 、酒 、笔记 和一 汽 。他出 26000美元。

希 的展 球 、 游戏、台球 和一 去巴 的 。 出 21500美元。

纳 展 的 格为25347美元。由 出 太 他 了 。

希 的展 的 格为21578美元。 起 格 只少猜了78美元 以 得了 。 为
的出 差少 250美元, 还 得了纳 的展 。

对一个 贝 维的人,这一场景暗示出的 个问题是:

1.在看到 ,选手对展示 的 格应 有什么 的先 分 断?

2.看到 后,选手应 修 这 期?

3.基 后 分 ,选手应 怎么出 ?

三个问题, 证了贝 分 的一个常 用 :决 分 。给 一个后 分 ,我们可以选择出


多少, 最大 度地 选手的 期收 。

这个问题来自 伦·戴维 - 隆的《Bayesian
Methods
forhackers》一 。我为 章 写的 可


http://thinkbayes.com/price.py 得 到 ; 入的 据可以 http://thinkbayes.com/showcases.2011.csv 和
http://thinkbayes.com/showcases.2012.csv下载。更多 息请参 的“ 指南”。

6.2
 先验
为了选择 格的先 分 ,我们可以利用先 的 据。 的是,这个 目的 详细记 了这
据。 我 戴维 - 隆先生就 通 时,他 了 ·吉收集的 据http://tpirsummaries.8m.com。
了 2011年到2012年的 目中 个展 环 的 格,还有参 选手就展 的出 。

图6-1显示了这 展 格的分 。最常 的展 大约是28000美元, 是 一 展 在50000美


元附近有个 征(线图稍微隆起的地 ), 展 的 格偶 会超过70000美元。
图6-1
“ 的 格” 目中展 格的分 ,2011-2012

这 分 基 的 据, 用 内 密度 进 了平滑(KDE)。在我们 续 ,我想绕道
先去 概率密度 和KDE。

6.3

到目 为 ,我们 和概率 量 PMF 了很多交道。PMF是 一个可能 到其概率的
射。在我的 现中,Pmf对象 一个Prob 法 得 和概率,也 称为概率 量。

在 学 示上,PDF通常写成一个 ;例 ,这里是均 为0, 准 差为1的 分 的PDF:

对 一个给 的x ,这个 可以 出概率密度。在更 的密度说 可能 也 这个 上,密


度和概率 量是 的。

是密度不是概率。密度可以是0 ;并非 概率那 在0和1 有界。

你在一个 续 对密度进 积分,其结 是一个概率。 在 中,我们很少这么用。


反,我们 要利用概率密度 为 然 的一部分。下 上会看到一个例子。

6.4
 PDF的 示
要在Python中 示PDF,thinkbayes.py 一个 为PDF的类。PDF是一个抽象类,这 着 了
PDF接口, 不 一个 整的 现。PDF接口 法,Density和MakePmf:
class Pdf(object):

def Density(self, x):
 raise UnimplementedMethodException()

def MakePmf(self, xs):
 pmf = Pmf()
 for x in xs:
pmf.Set(x, self.Density(x))
 pmf.Normalize()
 return pmf

Density取一个x ,并 应的密度。Makepmf生成PDF的近 散 。

Pdf 了makepmf的 现, 没有Density 法,Density 法必须通过子类来 。

实 类是 承自抽象类的一个子类, 了缺 法的 体 现。例 ,GaussianPdf扩展了Pdf并


了Density 法:
class GaussianPdf(Pdf):

def __init__(self, mu, sigma):
 self.mu = mu
 self.sigma = sigma

def Density(self, x):
 return scipy.stats.norm.pdf(x, self.mu, self.sigma)

__init__接受mu和sigma参 ,分 分 的平均 和 准 差,并 为 下来。

Density 用 scipy.stats 中的一个 来 PDF。这个 是 norm.pdf , 为 分 也称


为“ 态”分 。

PDF由一个 的 学 , 以 。 由 现 界中大量的分 都可以近 为


分 , 的用 也很大。

对 真 据,并不能 证分 是 其他的 学 。在这 情况下,我们可以用一


个 来 整体的PDF。

例 ,“ 的 格”中的 据,我们有313个 一 展 的 格。我们可以 为这 是展 格的


一个 。

示例 以下 ( 顺 ):

28800,
28868,
28941,
28957,
28958

在 中,没有出现28801和28867 的 , 是没有 由 为这 不 在。基 我们的 景


息,我们希望在这个 围内的 有 有 可能。 说,我们 PDF是非常平滑的。

内 密度 (KDE)是一 法, 找到一个恰 平滑的PDF进 据拟合。你可以


http://en.wikipedia.org/Wiki/Kernel_density_estimation了 到一 细 。
Scipy 了KDE的 现,thinkbayes则 了一个Estimated Pdf类 用 :
class EstimatedPdf(Pdf):

def __init__(self, sample):
self.kde = scipy.stats.gaussian_kde(sample)

def Density(self, x):
return self.kde.evaluate(x)

__init__ 集 内 密度 。其结 是一个 gaussian_kde 对象,并 了一个 evaluate


法。

Density接收 据,调用gaussian_kde.evaluate,然后 密度结 。

最后,这是生成的 干:
prices = ReadData()
pdf = thinkbayes.EstimatedPdf(prices)

low, high = 0, 75000
n = 101
xs = numpy.linspace(low, high, n) 
pmf = pdf.MakePmf(xs)

pdf是一个由KDE 的Pdf对象,pmf则是一个近 Pdf的Pmf对象, 通过在成 的 距


上的 密度 现。

示“线
linspace ”的 。 接收一个由low和high界 的 ,以 内的n个 据点,并
一个新的numpy , 含了n个low和high 的 距元 。

现在 到“ 的 格”问题。

6.5
 手建模
图6-1的PDF 了展 可能的 格分 。 你是一个参 目的选手,你可以 用这个分 来量
展 环 中的先 念(在看到 )。

要更新这 先 概率,我们必须 下 这 问题:

1.怎么看待 据以 量 据?

2.怎么 然 ? ,对 个 格给出什么 的 ,怎么 据的条件 然度?

为了 这 问题,我 选手 为一 误差 的 格猜 来 。 说, 选手看到
展 猜 个 的 格时——不 是展 一部分这一事 (也就是不 总量)—— 这
格 起来,得到的总和称为猜 格guess。

在这一 型下,我们必须要 的问题是
“ 格是 price ,选手的 格就是猜 格


guess的
然度?”

我们 :
error = price – guess (猜测误差 = 展品价格 – 猜测价格)
然后,我们可以 出问题“选手的 格 猜 误差error的 然度是什么?”

要 这个问题,我们要 用历 据。图6-2显示了diff的 积分 ,diff是参 的出 和


展示的 格 的差。

图6-2
 选手出 和 格差, 出 差diff的 积分 (CDF)

出 差diff的 是:
diff = price – bid  (出价差=奖品价格 – 选手出价)

diff的
是负的,出 就太 。 一 ,我们可以 用这个分 参 出 过 的概率:
一 选手 中出 的 例是25%; 选手 中出 的 例是29%。

我们也可以看到出 是不对称的; 选手更倾向出 。由 游戏 则这很好 。

最后,我们可以 用这个分 参 猜 格的可靠 (译 :由猜 误差 量的)。这一步有


点 手, 为我们真不 道选手的猜 格,只 道他们的出 。

此我们必须做出一 。 切地说是 为error的分 是一个和diff 差 ,均 为0的 分



class Player(object):

def __init__(self, prices, bids, diffs):
self.pdf_price = thinkbayes.EstimatedPdf(prices)
self.cdf_diff = thinkbayes.MakeCdfFromList(diffs)
mu = 0
sigma = numpy.std(diffs)
self.pdf_error = thinkbayes.GaussianPdf(mu, sigma)

prices 是一个展 格的 , bids 是一个选手出 的 , diffs 是一个出 差的 , diff


=price-bid。

pdf_price 是一个 格的平滑PDF,由KDE给出。 cdf_diff 是出 差的 积分 , 图6-2 示。


pdf_error是猜 误差分 的PDF,这里猜 误差=展 格–猜 格(error=price-guess)。

强调一下,我们 用 diff 的 差 error 的 差,这并不 美。 为选手的报 有时是有 略


的。例 , 选手2 为选手1出了 ,选手2可能会 用一个非常 的报 。在这 情况下出 差
diff就没有反 出猜 误差error。 发生较多这 情况, 到的diff 差会 猜 误差error的
差。然 ,我 为这是一个合 的 。

准 参 的人可以通过看以 的 ,记 下自己猜 格和 格的猜 误差, 自己猜


误差error的分 。

6.6
 似然
现在我们准 好编写 然 了。像通常那 , 一个新类:
class Price(thinkbayes.Suite):
def __init__(self, pmf, player):
thinkbayes.Suite.__init__(self, pmf)
self.player = player

pmf 了先 分 ,player是一个 章 的Player对象。Likelihood 下:


def Likelihood(self, data, hypo):
 price = hypo
 guess = data

 error = price - guess
 like = self.player.ErrorDensity(error)

 return like

hypo是展示 格的 。data是选手的最佳猜 格。error是他们的差,like是给 后 据的可


能 。

ErrorDensity在Player中 :
# class Player:
 def ErrorDensity(self, error):
return self.pdf_error.Density(error)

ErrorDensity通过给 的 误来 pdf_error,结 是概率密度。 此 并不是真是一个概率。


请记住Likelihood不 要 概率; 只 要 例,只要 有likelihood的 例 是 的,我们
对后 分 进 归一 后就没问题了。

以说概率密度是一个 好的 然度 法。
6.7
 更新
Player 了一个 法以选手的猜 来 后 分 :
# class Player

 def MakeBeliefs(self, guess):
pmf = self.PmfPrice()
self.prior = Price(pmf, self)
self.posterior = self.prior.Copy()
self.posterior.Update(guess)

PmfPrice生成PDF的 散近 格,我们用其构 先 概率。

PmfPrice 用MakePmf, pdf_price 的 :


# class Player

 n = 101
 price_xs = numpy.linspace(0, 75000, n)

 def PmfPrice(self):
return self.pdf_price.MakePmf(self.price_xs)

为了得到后 概率,我们先 先 概率,然后调用Update Update在 , 中调用Likelihood 一


,用先 以 然度,最后归一 。

让我们 到最 的场景。 你是选手1, 看到展 后你最佳的猜 是“ 的总 格是20000美


元”。

图6-3显示了 格的先 概率和后 概率。后 概率 , 为你猜 的是先 概率的



图6-3
 基 一个20000美元 格的最佳猜 ,选手1的 和后 分

在 度上这个结 是有 的。在先 上最有可能的展 格 是27750美元,你最好猜 是


20000美元, 后 概率的均 在25096美元上下。

一个 度上,你可能会发现这个结 的悖 , 为 你 为 格是20000美元,那么
在 猜 误差的情况下,你应 格是24000美元。

要想 决这个 显的矛盾,请记住你结合了 个 息来 ,过去展 的历 据和你看到 后 出


的猜 。

我们 的历 据 先 概率和然后基 你的猜 去修 。 的,我们也可以用你的猜


为先 基 历 的 据进 修 (译 :修 和更新都是Update的 译,结合上下 用)。

你可以这么 ——最有可能的展 格并不是你最 的猜 —— 是这一点也就没那么


了。
6.8
 最优出
现在我们有一个后 分 ,我们可以 用 来 最优报 ,我 为 期收 最大 的报 (
http://en.wikipedia.org/wiki/Expected_return)。

我 在 中 用自 向下的 法,这 着我 先 示怎么 用, 示为什么 此。 你看到


一个陌生的 法,不要担心,后 接着就是 。

为 最优报 ,我写了一个类称为GainCalculator:
class GainCalculator(object):

 def __init__(self, player, opponent):
 self.player = player
 self.opponent = opponent

Player和opponent都是Player对象。

GainCalculator ExpectedGains,为 出 和 期收 :
def ExpectedGains(self, low=0, high=75000, n=101):
 bids = numpy.linspace(low, high, n)

 gains = [self.ExpectedGain(bid) for bid in bids]

 return bids, gains

low和high 示了出 可能的 ;n是报 的 。

ExpectedGains调用ExpectedGain, 对 一个给 的报 的 期 :
def ExpectedGain(self, bid):
 suite = self.player.posterior
 total = 0
 for price, prob in sorted(suite.Items()):
gain = self.Gain(bid, price)
total += prob * gain
 return total

ExpectedGain 历后 概率的 ,给 展 的 格后 出 的 报。 对概率进


然后 总和。

ExpectedGain调用Gain,Gain通过报 和 格 期收 :
def Gain(self, bid, price):
 if bid > price:
return 0

 diff = price - bid
 prob = self.ProbWin(diff)

 if diff <= 250:
return 2 * price * prob
 else:
return price * prob

你出 了 一无 。反过来,我们 出 和 格的差,这个决 了你 的概率。

差异小 250美元你就 了。为 起 ,我 展 有 的 格。 为这个结 是 的,


成的差 不大。

最后,我们要基 diff 的 的概率:


def ProbWin(self, diff):
 prob = (self.opponent.ProbOverbid() + 
self.opponent.ProbWorseThan(diff))
 return prob

你的对手出 ,你 。 则的 ,你必须希望你的对手的出 差大 这个diff ,Player


了一 法来 这 个可能 :
# class Player:

 def ProbOverbid(self):
return self.cdf_diff.Prob(-1)
def ProbWorseThan(self, diff):
 return 1 - self.cdf_diff.Prob(diff)

这段 可能有 人 , 为这一 过 是以对手的 度进 的,对手 的 是“我出


的可能 是多少?”和“我的出 差超过diff的概率是多少?”

案都是基 diff 的CDF。 对手的差异小 1,你 。 对手的 diff 你大,你


。 则你 。

最后, 最优报 的 :
# class Player:

 def OptimalBid(self, guess, opponent):
self.MakeBeliefs(guess)
calc = GainCalculator(self, opponent)
bids, gains = calc.ExpectedGains()
gain, bid = max(zip(gains, bids))
return bid, gain

给 一个对手和guess,OptimalBid 出后 分 , 例 一个GainCalculator 可能
的 期收 报并 最优报 和 期收 。太棒了!

图6-4显示了基 这 一个场景下的结 ,选手1的最佳猜 是20000美元,选手2的猜 是40000美


元。
图6-4
 选手1的最佳猜 是20000美元,选手2的最佳猜 是40000美元时, 期收 的对 。

选手1的最优报 是21000美元,产生近16700美元的 期 报。

这是一个显得很不寻常的最优报 其 选手的最佳猜 一点的案例。

选手2的最优报 是31500美元,产生近19400美元的 期 报。这 最优报 小 最佳猜 的情况更


型。

6.9
 讨
贝 的
点 一就是结 来自后 分 这 形式。 的 通常会生成一个 一的点
, 就是过 的最后一步,这是 的。 你想以一个 为后续分 的 入,点
和 隔往往没有多少帮助。

在这个例子中,我们 用后 分 来 最优报 。给 出 的 报是不对称和不 续的( 你


,游戏 ), 以 分 很 决这个问题。 用 的 法就 对 。

贝 法的 学 常常通过均 最大 然 来描 后 分 ,这 概 是有用的,不过
你 要的 就是这 内 ,也许一开始就不必 贝 法。
在你 要 后 概率带入后续分 进 型决 时,贝 法就 有用了,就 我们在 章做
的一 。 外,进 时,贝 法也很有用,下一章我们会看到案例。

第7 
 预测

7.1
 士 队
在2010—2011的国家冰球 (NHL)总决 中,我 爱的7个 军波 顿 熊 我嗤 以鼻
的 哥华 大人 对决。波 顿以0
:
1和2
:
3 了 场 ,以8
:
1和4
:
0 了后续 场 。那么
在 的这个时 点上, 波 顿 下一场 的可能 是多少? 得总 军的概率是多少?

往常一 ,要 这 的问题我们 要做一 。首先,有 由 在冰球 中的入球得分至


少近 松过 ,这 着在 的 时 上都有 的得分可能。

其 ,我们可以 , 期来看对 一个 的对手, 都有一个 场平均得分 ,记为λ。

根据这 ,我 这个问题的 略是:

1. 以 的 统 料,为λ选择一个先 分 。

2.由 四场 的得分 的λ。

3.用λ的后 分 来 的入球分 ,得分差的分 ,还有 个球 下一场 的概率。

4. 个 得 军的可能 。

要选择一个先 分 ,我 http://www.nhl.com
 得了一 统 字, 体 在2010—2011


平均 场入球的分 ,大 是均 为2.8, 准差为0.3的 分 。

分 是 续的, 我们会用 散的
Pmf
近 , thinkbayes 了 下的 MakeGaussianPmf


现:
def MakeGaussianPmf(mu, sigma, num_sigmas, n=101):
    pmf = Pmf()
    low = mu - num_sigmas*sigma
    high = mu + num_sigmas*sigma

    for x in numpy.linspace(low, high, n):
        p = scipy.stats.norm.pdf(mu, sigma, x)
        pmf.Set(x, p)
    pmf.Normalize()
    return pmf

mu和sigma是 分 的均 和 准 差。num_sigmas是 和 Pmf均 的 准 差 量,n为Pmf


中条目的个 。

一 ,我们 用numpy.linspace构 一个在上下界 ( 界)上有着 隔 的n个条


目的 。

norm.pdf 出 概率密度 (PDF)。

到 问题上,下 是一 有 λ 的 。
class Hockey(thinkbayes.Suite):

    def __init__(self):
        pmf = thinkbayes.MakeGaussianPmf(2.7, 0.3, 4)
        thinkbayes.Suite.__init__(self, pmf)
这 的先 分 是均 2.7, 准 差0.3的 分 , 围是上下以均 为中心的4个sigma。

一 以往,我们必须决 示 个 ,在这 情况下,我 λ
=
x(x是浮点 ) 为 。

7.2
 松过程
在 统 上,过程是一个物 统的 型(“ ”是指 型 含 量)。例 ,一个
伯努利过 是一个事件 的 型,称为试 ,其中 个试 有 可能的结 , 成功和 。
此,对 一 的 币翻转事件, 一 的射击得分事件,伯努利过 是一个天然的 型。 松过
是伯努利过 的 续 ,一个事件在 时 点上发生的概率是 的。 松过 可应用 到达 店的
客户, 交 到站, 冰球 的入球得分上。

在许多 统中,事件的概率 时 变 。客户在一天的 时段去 店的可能 更 , 交 应


以固 的 隔到达, 中不 的时 段的得分有 分。

有 型都是为了 事物,在这 情况下,以 松过 真冰球 是一个合 的选择。豪雅,


勒 和 纳 ( 2010 ) 分 德 国 球 的 得 分 , 得 出 了 的 结 ,
http://www.cimat.mx/Eventos/vpec10/img/poisson.pdf。

用 型的优点是,我们可以有效 出 场 入球的分 以 入球时 点 隔的分 。 体


地, 一场 平均入球 是lam, 场 入球的分 可由 松PMF给出:
def EvalPoissonPmf(lam, k):
    return (lam)**k * math.exp(-lam) / math.factorial(k)

得分 隔的分 由指 型PDF给出
:
def EvalExponentialPdf(lam, x):
    return lam * math.exp(-lam * x)

我用了变量
lam, 为
lambda是
Python
中的 键字。这 个 都在thinkbayes.py中。

7.3
 后验
现在,我们可以 一个给 lam 的球 在一场 中进k个球的可能 :
# class Hockey

    def Likelihood(self, data, hypo):
        lam = hypo
        k = data
        like = thinkbayes.EvalPoissonPmf(lam, k)
        return like

个 都是λ的一个可能的 ; 据是得分k,利用这里的 然 ,我们可以为 个球 准 一个


suite对象,接着用 四场 的得分进 修 。
    suite1 = Hockey('bruins')
    suite1.UpdateSet([0, 2, 8, 4])

    suite2 = Hockey('canucks')
    suite2.UpdateSet([1, 3, 1, 0])
图7-1显示了给 lam的后 分 结 。根据 四场 的 据,最有可能的lam 大人 是2.6,
熊 是2.9(译 :冰球 进一球得到一分, 此对“得分”和“入球”结合上下 灵活 用)。

图7-1
 场 入球 的后 分

7.4
 球分布
要 个团 得下一场 的概率,我们 要 球 得分的分 。

我们 道 切的lam取 ,我们可以 用 松分 。thinkbayes 了一个 法 松分


的分段近 :
def MakePoissonPmf(lam, high):
    pmf = Pmf()
    for k in xrange(0, high+1):
        p = EvalPoissonPmf(lam, k)
        pmf.Set(k, p)
    pmf.Normalize()
    return pmf

的Pmf 的 围 0到high。 以, lam 为3.4,我们可以 下:


lam = 3.4
goal_dist = thinkbayes.MakePoissonPmf(lam, 10)
我选择了上界10, 为 中得分超过10球的概率是 的。

目 为 这 都很 ,问题是我们不 道lam的 切 。不过还好,我们有lam可能 的分 。

对 lam的 一个 ,得分是 松分 。这 得分的整体分 就是这 松分 的 合分 ,根据lam


分 的概率进 。

给 lam的后 分 ,下 是 得分分 的 :
def MakeGoalPmf(suite):
    metapmf = thinkbayes.Pmf()

    for lam, prob in suite.Items():
        pmf = thinkbayes.MakePoissonPmf(lam, 10)
        metapmf.Set(pmf, prob)

    mix = thinkbayes.MakeMixture(metapmf)
    return mix

对 lam的 一个 ,我们创 一个 松Pmf,并 到元Pmf。我称其为元Pmf,

为 是一个 含多个Pmfs 的Pmf对象。

然后我们用MakeMixture 合分 (参 MakeMixture的“ 合分 ”, 45 )。

图7-2
显示了由此产生的 熊 和 大人 的入球分 。 熊 在接下来的 中不太可能只进不


到3球,更可能进4球以上。
图7-2
 场 入球分

7.5
 获 的
为了得到 的概率,首先我们 入球得分差异的分 :
    goal_dist1 = MakeGoalPmf (suite1)
    goal_dist2 = MakeGoalPmf (suite2)
    diff = goal_dist1 - goal_dist2

减法 符调用Pmf.__sub__, 枚 一对 ( 得分)并 差 。 个分 的差和 操


一 , 我们在 40 “ ”看到的。

得分差 是 的, 熊 ; 为负, 大人 ; 是0,就是平 :


    p_win = diff.ProbGreater (0)
    p_loss = diff.ProbLess (0)
    p_tie = diff.Prob (0)

由 一 中的得分的分 看,p_win是46%,p_loss是37%,p_tie为17%。

在 时 结束时 出现平 , 会进 时 ,直到其中一 得分。由 一 入球 就


会 上结束,这 时 形式 称为“ 然 法则”。
7.6
 突然死 则
为了 在 时 通过“ 然 法则” 球的概率,重要的统 指 不是 场 入球 , 是 一
个入球的时 。 的入球是一个 松过 , 着得分 的时 服 指 分 。

给 lam,我们可以 得分 的时 :
lam= 3.4
time_dist = thinkbayes.MakeExponentialPmf (lam, high = 2  , n = 101)

high是分 的上界。在这个例子中我选择2, 为超过2场 不入球的概率是很小的。n是Pmf里


的个 。

我们 道lam的 切 ,这就是 部 要的 了。 我们不 lam,我们 道的是lam 可能


的后 概率分 。

以, 我们在 得分分 中做的一 ,我们创 一个元Pmf并 Pmfs的 合物。


def MakeGoalTimePmf(suite):
    metapmf = thinkbayes.Pmf()

    for lam, prob in suite.Items():
        pmf = thinkbayes.MakeExponentialPmf(lam, high=2, n=2001)
        metapmf.Set(pmf, prob)

    mix = thinkbayes.MakeMixture(metapmf)
    return mix

图7-3显示了生成的分 。对 时 小 1 ( 的1/3,1场 有3 ), 熊 更 得分。 时


时 得越 , 大人 越可能得分。
图7-3
 得分 的 隔时 分 (时 以 场 )

我 了 的n ,以最大 度地减少平 的 量, 为 支球 是不可能 时得分的。

现在我们 熊 首先得分的概率:
    time_dist1 = MakeGoalTimePmf (suite1)
    time_dist2 = MakeGoalTimePmf (suite2)
    p_overtime = thinkbayes.PmfProbLess (time_dist1  , time_dist2)

对 熊 , 得 时 的概率为52%。

最后, 的总概率为常 时 得 的 会 上 时 得 的概率。


    p_tie = diff.Prob (0)
    p_overtime = thinkbayes.PmfProbLess (time_dist1  , time_dist2)
    p_win = diff.ProbGreater (0)+ p_tie * p_overtime

以对 熊 , 的下一场 的整体概率是55%。

要 得整个 (总决 )的 , 熊 可以在下 场 中 在接下来 场中 一场


得 三场。 ,我们可以 出总的概率:
    # win the next two
    p_series = p_win**2
    # split the next two, win the third
    p_series += 2 * p_win * (1-p_win) * p_win

此 熊 得 总 军的 会是57%。在2011年,他们 做到了。

7.7
 讨
往常一 , 章讨 的分 是基 型决 的, 总是一个反 的过 。

一般情况下,你要 一 的能产生近 案的 型开始,找出 误的可能来 ,并找到 会来改


进 型。

在这个例子中,我会 以下选项:
 

我为 支 伍选择了一个基 平均得分的先 。 这个统 是 有对手的平均 。 对 一 的对


手,我们可以更灵活 。例 , 最好锋线的 伍和最 糕后防的 伍 , 得分 期目 可
以是平均 以上的 个 准 差。
据,我只用了 军 四场 的 据。 只球 在常 过,我可以 用常 的
结 据。有 杂的是球 成 在这期 的变动——由 受 和 内的球 交 , 以最好给近
期的 结 更多的 。
为了充分利用 有可用的 息,我们可以 有常 得分 的入球率,用 只 伍 的
结 进 进一步的 度修 。这 做会有 杂, 然是可 的。

对 一 选择,我们可以用常 的 结 伍 的变 量。要感 德克· 格,我


http://forechecker.blogspot.com,上 得了常 场 的入球得分 (不含 时 )。

不 的 伍在常 1 到2 , 以我 重点 在进 4到6场 的 伍上。对 一对


球 ,我 他们 场 的平均入球 为λ的 ,然后绘 的分 。

这 的均 为2.8,不过 准差为0.85, 我们 就 支 伍 的更 。

我们 用这一较 的 差 进 概率分 , 熊 得 的概率是80%, 用较


差得到的57% 很多。

以,事 证 ,这一结 对先 概率是敏感的, 此自然 我们 ,究竟 用多少 据进 分


合 。

到不 型会产生的差异( 差和 差),这 说 得我们 入一 来 得合 的


概率。

章的 和 据 都 可 以 http://thinkbayes.com/hockey.py 和 http://thinkbayes.com/hockey_data.csv
得。 了 更多 息,请参 的“ 指南”。

7.8
 习
练习7-1。
交 到站 隔是20分 ,你到达 交站的时 是 的,那么你 待 交 的时 0到20分
均 分 。 在现 中, 交 达的 隔是有变动的。 你 在 待一 交 , 你 道
交 达时 的历 分 。 你 待时 的分 。

示: 交 隔为 概率的5分 10分 。你 好在一个10分 发 隔中到达 交站的概


率是多少?

我在下一章 了这个问题的一个 法。

练习7-2。

客到达 交 站是一个参 为
λ
的 想 松过 。 你到达 站,发现有
3人在 待,对你


,距 上一趟 交 达过去了多 时 的后 分 是什么?

我下一章 了这个问题的一 法。

练习7-3。

你是一位在新的环境中进 取 的生态学家。

你在 试地 了100个 , 天 去 查 们。你发现有37个 触发捕 。一


触发, 就不能 续捕 其他昆 直到 位。

你重 , 天后(内) 来,你 期发现多少 触发的 ? 这一后 / 的分 。

练习7-4。

你是一个管 有100个灯泡 寓的大楼 。你的责 是在灯泡 时更 灯泡。

1月1日, 有100个灯泡都是好的。 你2月1日 查时,你发现有3个灯泡 。 你4月1日 来


查,你 期会有多少灯泡坏 ?

在 的练习中,你可以合 地 一个事件在 时 发生的概率 。对 灯泡, 效的可能


取决 灯泡的 命。 体 ,旧灯泡的故障率会 着灯 的蒸发 。

这个问题 其他问题更开 ,你 不得不 出决 型。

你可能要了 一下Weibull分 (http://en.wikipedia.org/wiki/Weibull_distribution)。 寻找一 灯泡


命 线的 息。

第8 
 观 的 差

8.1

在 诸 ,“红线”是 接 桥和波 顿的地 线路。我在 桥工 的时 坐红线地 Kendall
广场到南站, 转 通 路到Needham。上下 峰期,红线 平均 7~8分 一趟。

到达 站时,我可以根据站台上的 客人 下一 到达的时 。 只有 个人,就


过了地 ,下一 地 要 约7分 。 站台上有较多 客,就 地 会很快到达。 是
有 多的 客,则要怀 未能 期 , 以会 到 上 出 出 。

在 待 时,我 了怎 通过贝 帮助我 待时 ,并决 什么时 应 坐


改为 坐出 。 章 我 用的分 过 。

章内 自Brendan
Ritter和Kai
Austin负责的一个项目,他们和我在欧 学 一个 。 章中
的 可 以 http://thinkbayes.com/redline.py 得 到 。 我 用 来 收 集 据 的 在
http://thinkbayes.com/redline_data.py。 了 更多 息,请参 的“ 指南”。

8.2
 模型
在分 ,我们必须决 一 细 。首先,我 客 达 站 松过 ,这 着我
客可能在 时 概率到达, 客有一个未 的到达率λ,以 分 到达的 客 量。 为我在很 的
时 段内 察 客, 是在 天的 一时 , 以我 λ为常 。

一 , 的到达过 不是 松的。 峰时 点(灰西鲱站)去波 顿的 隔7~8分


发出, 到Kendall广场的时 , 隔在3~12分 内变 。

为 了 收 集 发 隔 的 据 , 我 编 写 了 下 载 时 据 的 脚
http://www.mbta.com/rider_tools/developers/,选择往南到达Kendall广场的 ,并在 据库中记 其到达
时 。脚 在 个工 日下午4点到下午6点 , 续5天, 天记 了
15 到达。然后我 后
到达 的时 隔,这 分 的差 图8-1
 示, 为z。
图8-1
 根据收集到的 据绘 的 隔的PMF,以KDE平滑
(z为 分 ;zb是由 客看到 隔的 差分 ) 


你下午4点到下午6点在站台记 的 隔,这就是你看到 隔时 的分 。 是 你
到达站台(不管 时刻 ),会看到一个 此不 的分 , 到达的 客 看到的 隔的平均
, 的平均 要 一 。

为什么? 为 客到达的时 隔更可能是一个较大的 。 一个 的例子: 隔是


5分 10分 ( 的概率)。在这 情况下, 的平均时 是7.5分 。

客更可能在10分 的时段内到达 不是在5分 内,事 上 是后 的 倍。 我们调查到


站 客会发现,其中2/3在10分 的时段内到达,5分 时段内到达的只有1/3。 以到站 客 察到的
隔平均 是8.33分 。

这 观 差在许多情况下出现。学生们 为 的要大是 为他们 常上大 , 上的


客 为 更 是 为他们常常 坐 的 。

在 情况下, 分 中的 都 例 过 了。例 ,在红线上,差距就是 倍大。

以,有了 隔的 分 ,我们可以 得到 客看到的 隔分 。BiasPmf进 这个



def BiasPmf(pmf):
    new_pmf = pmf.Copy()

    for x, p in pmf.Items():
        new_pmf.Mult(x, x)

    new_pmf.Normalize()
    return new_pmf

pmf是 的分 ;new_pmf是 分 。在 环中,我们 个 的概率x 以 到的 然度,其


x,然后我们对结 归一 。

8.3
 等 时间
待时 称 为y,是 客到达时刻和下一趟 到达时刻 的时 。 过时 称 为x,是 客到
达时刻和上一趟 到达时刻 的时 。这 得zb = x +y。

给 zb的分 ,我们可以 出y的分 。我先 一个 的情况开始,然后 一般 。


的例子,zb为5分 的概率是1/3,10分 的概率就是2/3。

我们在5分 隔内 到达,y均 分 0至5分 内。 我们在10分 的 隔到达,y均


分 0到10分 内。 以整体分 是根据 一个 隔的概率 了的均 分 的 合分 。

下 的 zb的分 和y的分 :
def PmfOfWaitTime(pmf_zb):
    metapmf = thinkbayes.Pmf()
    for gap, prob in pmf_zb.Items():
        uniform = MakeUniformPmf(0, gap)
        metapmf.Set(uniform, prob)

    pmf_y = thinkbayes.MakeMixture(metapmf)
    return pmf_y

PmfOfWaitTime通过 射 个均 分 和其概率来构 一个元Pmf。然后, 用45 “ 合分 ”中的


MakeMixture, 合分 。

PmfOfWaitTime还 用了MakeUniformPmf, 为:
def MakeUniformPmf(low, high):
    pmf = thinkbayes.Pmf()
    for x in MakeRange(low=low, high=high):
        pmf.Set(x, 1)
    pmf.Normalize()
    return pmf

low 和 high 决 了均 分 的 围(含 端)。最后, MakeUniformPmf 用了 MakeRange ,此


为:
def MakeRange(low, high, skip=10):
    return range(low, high+skip, skip)

MakeRange 了一 待时 (以 示)的可能 。默 情况下, 围 分为10 的时


隔。

为了封 这 分 的 过 ,我创 了一个类WaitTimeCalculator:


class WaitTimeCalculator(object):

    def __init__(self, pmf_z):
        self.pmf_z = pmf_z
        self.pmf_zb = BiasPmf(pmf)

        self.pmf_y = self.PmfOfWaitTime(self.pmf_zb)
        self.pmf_x = self.pmf_y

参 pmf_z 是 z 的非
差分 。pmf_zb是 客看到的 隔的 差分 。pmf_y是 待时 的分 。
pmf_x 是
过的时 的分 , 和 待时 分 是一 的。想 道为什么?记得对 一个 zp 的一个
,y的分 是 0到zp均 的, 到x = zp – y, 此x的分 也是 0到zp均 的。

图8-2显示了z、zb和y的分 ——基 我 Red
Line 站上收集的 据。

图8-2
 z,zb, 客 待时 y的CDF

为了 这 分 ,我 Pmfs切 到Cdfs。大多 人都更 悉Pmfs, 我 为一 你习 了,Cdfs更


。 要在 一坐 上绘 多个分 ,就应 用Cdfs。

z的平均 为7.8分 。zb的平均 为8.8分 , 出z约13%。y均 为4.4分 ,是zb均 的一 。

顺便 一下,根据红线调度站的报告显示,在 峰期 隔是9分 / 。这接近 zb 的平均


, z的平均 。通过 MBTA 路 的 件 通,报告中的 隔时 是有 的,以
一 旋余地。
8.4
 预测等 时间
让我们 到 始问题: 想一下, 我到达站台时看到有10人在 待。在下一 到达 ,我 期要
待多 时 呢?

往常一 ,让我们 这个问题的最 的 开始,然后找到最 案。 我们给出z的 分


, 我们 道 客到达率λ是 分 2 客。

在这 情况下,我们可以:

1.用z的分 来 zp的先 分 , 客 看到的 隔分 。

2.然后,我们可以 用 客 量来 x的分 , 上一趟 开后 过的时 。

3.最后,我们 用 y = zp - x可得y的分 。

一步是创 一个WaitTimeCalculator,封 zp,x和y的分 ——在 客的 目 。


    wtc = WaitTimeCalculator(pmf_z)

pmf_z是给 的 隔时 的分 。

接下来的步 是创 一个ElapsedTimeEstimator, 封 了x的后 分 和y的 分 。


    ete = ElapsedTimeEstimator (wtc ,
                                lam= 2.0/60 ,
                                num_passengers = 15)

参 是WaitTimeCalculator, 客到达率lam( 示为 客人 / )和站台上看到的 客 量(


是15)。

ElapsedTimeEstimator的 :
class ElapsedTimeEstimator(object):

    def __init__(self, wtc, lam, num_passengers):
        self.prior_x = Elapsed(wtc.pmf_x)

        self.post_x = self.prior_x.Copy()
        self.post_x.Update((lam, num_passengers))

        self.pmf_y = PredictWaitTime(wtc.pmf_zb, self.post_x)

prior_x和posterior_x是 过时 的先 和后 分 。pmf_y是 待时 的 分 。

ElapsedTimeEstimator 用Elapsed和PredictWaitTime, 下。

Elapsed是 示x的 想分 的Suite对象。x的先 分 直接由WaitTimeCalculator得到。然后,我们


用这 据, 到达率,lam和站台上 客的 量 后 分 。

下 是Elapsed的 :
class Elapsed(thinkbayes.Suite):

    def Likelihood(self, data, hypo):
        x = hypo
        lam, k = data
        like = thinkbayes.EvalPoissonPmf(lam * x, k)
        return like
往常一 ,Likelihood接受一个 和 据,并 下 据的 然度。在这个例子里 hypo
是上一趟 后 过的时 ,data是一个 lam和 客 量的元 。

据的 然度是给 到达率lam下,x时 内k 达的概率。我们利用一个 松分 的PMF来


最后,PredictWaitTime的 是:
def PredictWaitTime(pmf_zb, pmf_x):
    pmf_y = pmf_zb - pmf_x
    RemoveNegatives(pmf_y)
    return pmf_y

pmf_zb 是 隔的分 情况;pmf_x 是 过时 的分 (根据对 客 量的 察得到)。由 y =


zb - x,我们可以 :
    pmf_y = pmf_zb - pmf_x

减法 符调用Pmf.__sub__,其中 了 有zb和x对, 其差, 结 总到pmf_y。

由此产生的Pmf 一 显然不可能的负 。例 , 你是在5分 的 隔期 到达的,你的 待


时 不可能超过5分 。RemoveNegatives会 除这 不可能的 并重新归一 。
def RemoveNegatives(pmf):
    for val in pmf.Values():
        if val < 0:
            pmf.Remove(val)
    pmf.Normalize()

图8-3显示了结 。x的先 分 和y一 。x的后 分 ,看到站台上的15 客后, 到自上


一趟 过后的时 大概是5~10分 , 以我们 下一 会在5分 内到达, 度为80%。
图8-3
 x的先 分 和后 分 ,以 的y

8.5
 到达
到目 为 的分 基 我们 (1) 隔的分 (2) 客到达率的 。现在,我们 准
好开始 个 。

你 到波 顿, 以你不了 红线地 的 客到达率。利用 天上下 时 ,就可以做至少是


可量 的猜 。只要 花一点心 ,你甚至可以 量的 λ。 一天你到达站台时,你应 时 和
到达 客的 量( 站台太大,你可以选择一个 域)。然后记 自己的 待时 ,以 在你 待
期 新到站的 客 量。

5天后,你可能得到这 的 据:
k1      y      k2
--     ---     --
17     4.6      9
22     1.0      0
23     1.4      4
18     5.4     12
4      5.8     11

其中k1是 你到达时, 在 的 客 ,y是你的 待时 ,k2为 待期 到达的 客 量。


一个多星期的记 中,你 待时 是18分 ,看到36 客到达, 此可以 ,到达率是 分 2
客。就 来说,这一 了, 为了 整起 ,我会 λ的后 分 ,然后 示怎么 在后
的分 中利用 分 。

ArrivalRate是个 λ 的Suite对象。 往常一 ,Likelihood接收 和 据, 出 下的


据 然度。

在例子里 , 是λ的取 。 据是y、k 据对,其中y是一个 待时 ,k是到达的 客人 。


class ArrivalRate(thinkbayes.Suite):

    def Likelihood(self, data, hypo):
        lam = hypo
        y, k = data
        like = thinkbayes.EvalPoissonPmf(lam * y, k)
        return like

这一Likelihood看起来很 悉, 和 75 “ 待时 ”里的Elapsed.Likelihood 一 一 。
在 Elapsed.Likelihood里 是 过的时 x,在ArrivalRate.Likelihood里 是lam到达率。
个例子里 , 然度都是在 lam的条件下,一段时 里 到k个到达( 客)的可能 。

ArrivalRateEstimator 封 λ的过 。参 passenger_data ,是一个 k1 , y , k2 元 的元 ,


体 据 示。
class ArrivalRateEstimator(object):

    def __init__(self, passenger_data):
        low, high = 0, 5
        n = 51
        hypos = numpy.linspace(low, high, n) / 60

        self.prior_lam = ArrivalRate(hypos)
        self.post_lam = self.prior_lam.Copy()
        for k1, y, k2 in passenger_data:
            self.post_lam.Update((y, k2))

__init__构 ,这是lam 的 ,然后生成先 分 prior_lam。for 环以 据更新 概


率,产生后 分 post_lam。

图8-4给出了先 和后 分 。 期的那 ,均 和中位 都在 察得到的 附近, 分 2


客。 我们不 后 分 的 围是 是由 λ基 小 的原 。
图8-4
 基 5天 客 据的lam的 和后 分

8.6
 消除不确定
无 时,分 中总有一 入量带来的不 ,我们可以通过下 这个步 这一 进
来:

1. 现基 不 参 的 分 (在 例中是λ)。

2. 不 参 的分 。

3.对参 的 个 进 分 ,并生成一 分 。

4. 用参 分 对应的 出 分 的 合分 。

我们 成了步 1和步 2。我写了一个类WaitMixtureEstimator 步 3和步 4。


class WaitMixtureEstimator(object):

    def __init__(self, wtc, are, num_passengers=15):
        self.metapmf = thinkbayes.Pmf()

        for lam, prob in sorted(are.post_lam.Items()):
            ete = ElapsedTimeEstimator(wtc, lam, num_passengers)
            self.metapmf.Set(ete.pmf_y, prob)

        self.mixture = thinkbayes.MakeMixture(self.metapmf)
wtc是 含zb分 的WaitTimeCalculator 例。are则是 含了lam分 的ArrivalTimeEstimator 例。
一 创 了 一 个 元 Pmf 来 射y的可能分 和其概率。对 lam 的 一个 ,我们用
ElapsedTimeEstimator y的 应分 ,并 其 储在元Pmf。然后我们用MakeMixture来 合分 。

图8-5显示了结 。 景中的 线 示了y对应 lam 个 的分 ,细线 示 然度。粗线是这


分 的 合分 。

图8-5
 对应了lam 有可能 的y的 分

在这 情况下,我们可以用lam的 点 得到一个非常类 的结 。 此就 用 , 的不
含进来不是必 的。

在一般情况下, 统 应是非线 的,那么 可变 就很重要了。此时, 入的微小变 都会


起 出的较大变 , 例中,lam的后 变 很小,对 小的扰动, 统的 应近 线 。

8.7
 决 分
现在,我们可以 用站台上 客人 待时 的分 了。让我们 问题的 部分:我应 在
时 待 去 一 出 ?
请记住,在 始的场景中,我会去南站 坐通 路。 我下 早, 以 以 待15分 在南
站 。

在这 情况下,我想 道的是“y超过15分 ” 为num_passengers的 的概率。用“ 待时 ”里


的分 法这很 。在num_passengers的 上 这个分 。

有一个问题。 分 对 时 延误的 敏感, 由 时 延误 , 此很 其时 延误


发生 。

我只有一 的 据, 察到的最 延误是15分 。 以我无法准 时 延误的 。不过我还


是可以 用以 的 察来进 至少是粗略的 。

在一年时 坐红线的过 中,我看到了由 问题、 、其他 站的 察 动 成的3个 时


延误, 以我 大约 年有3 时 延误。

请记住我的看法是 颇的。我更倾向 察 时 延误是 为 们 了大 客。 以,我们应


我的 为zb的 , 不是z的。下 是我们怎 做到这一点。

在 坐地 通 那一年,我 坐红线约220 。 以我用 察到的 隔时 gap_times 产生了220个


隔的 ,并 们的Pmf:
    n = 220
    cdf_z = thinkbayes.MakeCdfFromList (gap_times)
    sample_z = cdf_z.Sample (n)
    pmf_z = thinkbayes.MakePmfFromList (sample_z)

接下来,我 pmf_z得到zb的分 情况,抽取 ,然后 了30分 、40分 和50分 的三 延


误(以 示):
    cdf_zp = BiasPmf (pmf_z ). MakeCdf()
    sample_zb = cdf_zp.Sample(n)+ [ 1800  ,2400 , 3000]

Cdf.Sample Pmf.Sample更 效, 一般会更快地 Pmf转 成Cdf。

接下来,我以zb的 用KDE来 Pdf,然后 Pdf转 为Pmf:


    pdf_zb = thinkbayes.EstimatedPdf (sample_zb)
    xs = MakeRange(low= 60)
    pmf_zb = pdf_zb.MakePmf (xs)

最后,我反 zb的分 来 得z的分 ,用z创 WaitTimeCalculator:


    pmf_z = UnbiasPmf (pmf_zb)
    wtc = WaitTimeCalculator (pmf_z)

这个过 是 杂的, 有的步 都是我们 过的操 。现在我们准 进 一个 时 待的


概率。
def ProbLongWait(num_passengers, minutes):
    ete = ElapsedTimeEstimator(wtc, lam, num_passengers)
    cdf_y = ete.pmf_y.MakeCdf()
    prob = 1 - cdf_y.Prob(minutes * 60)
根据平台上的 客人 ,ProbLongWait用ElapsedTimeEstimator 取 待时 的分 ,并 待时
超过minutes的概率。

图8-6显示了结 。 客的 目小 20,我们 断 统 常,此时 时 延迟的概率很小。


有30 客,我们 自上趟 过了15分 ;这 常延迟时 , 此我们 断出了 问
题,并 期会有更 的延迟。

图8-6
 以站台上 客人 为变量的 待时 超过15分 的概率

能接受有10%的概率会 过南站 , 有不到30 客的时 ,我们应 下来 续 待。


发现 客更多的 ,应选择 坐出 。

,进一步分 ,我们可以量 过南站 的成 和 坐出 的 用,然后选择最小 期成


的阈 。

8.8
 讨
分 到目 为 一直基 一个 , 客的到达率 天是 的,对 峰时段的通 ,这可
能不是一个坏 , 也有一 显的例外。例 , 附近有一个 殊的事件,大量的 客可能 时到
达。在这 情况下,lam的 就会太 , 以x和y的 会太 。
殊事件和重大延误一 常 , 们 进 型就很重要。我们可以通过扩展lam的分 以
进偶 出现的较大 来 现这一点。

我们是 z的分 开始的。 一个 法是 客可以 z,这也不 。 为 客,你只能


察到自己的 待时 y。除非你略过 到的 一 , 到站, 则你就不能直接 到
的 隔z。

不过,我们可以做出zb的一 。 我们 自己 达 站时的 客人 ,我们可以 自上一


趟 后 过去的时 x,然后 察y。 我们 x的后 分 到的y ,就得到了 示zb 的
后 念的分 。

我们可以利用这个分 来修 我们对 zb 的分 度。最 可以通过反向 BiasPmf zb 得到 z 的分


我 下一个分 练习给读 。 : 读 15章。你可以在http://thinkbayes.com/redline.py找到 法的


概。 了 更多 息,请参 的“ 指南”。

8.9
 习
练习8-1。

这一练习来自麦凯《 息 、 和学习 法》一 :

有不 的 子 一个 上射出,并 距 x的位 上衰减,x是含有参 λ的指 概率分 。


衰变只有在x
=
1 米到x
=
20 米的 口内 能 察到。 在距 1.5 米、2 米、3 米、4
米、5 米、12 米 到N个衰变,λ的后 分 是什么?

你可以 http://thinkbayes.com/decay.py下载这个练习的 法。

第9 
 二

9.1
 彩
射击 动中,参 伍用 互 射击,用涂料填充的 命中时会 碎。这一 动通常在一个
了障碍和其他可 为掩护物体的 域中进 。

你在一个宽30 50 的室内场地玩 ,靠近一 30 的墙壁站着,怀 你的对手 一


到了墙 附近。沿着墙壁,你看到 个有 颜色的 痕迹,可以 为你的对手 开 了。

痕迹是在沿着 下 墙 15 、16 、18 和21 。根据这 据,你 为你的对手


的位 在 里?

图9-1显示了场地的平 图。以 的 下 为原点。我以α和β 为射击 的未 位 坐 , 称为


alpha和beta。 痕迹位 记为x。对手射击的 度为
θ theta。

图9-1
 问题 图

问题是贝 分 案例中常 的灯 问题的一个修改 ,我的 依据了D.S.Sivia在一《


据分 :贝 ( )》(牛 出 社,2006年) 中对 问题的 。

你可以 http://thinkbayes.com/paintball.py
下载 章 。更多 息请参 的“ 指南”。

9.2
 Suite对象
首先,我们 要一个Suite对象来 示一 有 对手位 的 。 个 是一对坐 :(alpha,
beta)。

下 是 Suite对象的 :
class Paintball(thinkbayes.Suite, thinkbayes.Joint):

    def __init__(self, alphas, betas, locations):
        self.locations = locations
        pairs = [(alpha, beta) 
                for alpha in alphas 
                for beta in betas]
        thinkbayes.Suite.__init__(self, pairs)

Paintball 承自我们 过的Suite对象,至 Joint我会 上开始 。

alphas 是 alpha 有可能 的 , betas 是 beta 的 。 pairs 是 有的( alpha , bata )对的
。locations是沿墙的可能位 , 储在Likelihood中以便后 用。

为30 宽,50 ,下 是一个创 Suite对象的 :


alphas = range(0, 31)
betas = range(1, 51)
locations = range(0, 31)

suite = Paintball(alphas, betas, locations)

这个先 分 里的 有位 都 可能。 的地图后,我们可选择一个更详细的先 分


, 我们先 情况的开始。

9.3
 三角学
现在我们 要一个 然 ,这 着我们必须弄清 在 对手的位 后,他击中 一个沿着墙
壁的位 点的 然度。

为一个 型, 对手像一个旋转着的炮 ,向 向射击的可能 。在这 情况下,


他最有可能 中墙壁的alpha位 ,击中 alpha的位 可能 较小。

利用一 三 学 ,我们可以 击中 沿着墙壁点上概率。试想一下,射手以 度θ射击,


会击中墙上的位 x,其中

这个 得到θ

此, 墙上 个位 ,我们可以 出θ。

取 一 对 
θ
的导

这个导 我称 为“ 射速度”,这是目 着
θ
 沿着墙 动的速度(一个 射)。击中墙上一


个给 的点的概率和 射速度负 。
我们 道射手的坐 和墙壁上的一个位 ,我们就可以 出 射速度:
def StrafingSpeed(alpha, beta, x):
    theta = math.atan2(x - alpha, beta)
    speed = beta / math.cos(theta)**2
    return speed

alpha和beta是射手的坐 ;x是一个 的位 。结 是x 对 theta的导 。

现在,我们可以 出 示击中 位 概率的Pmf了。 MakeLocationPmf 接收的参 是射手的坐


alpla和beta; 命中的位 Locations(一个Locations可能 的 )。
def MakeLocationPmf(alpha, beta, locations):
    pmf = thinkbayes.Pmf()
    for x in locations:
        prob = 1.0 / StrafingSpeed(alpha, beta, x)
        pmf.Set(x, prob)
    pmf.Normalize()
    return pmf

MakeLocationPmf 出了击中墙上 个位 的概率,其反 射速度。其结 是位 的Pmf和 们


的概率。

图9-2显示了用alpha=10 和一 的beta 的Pmf 。对 试的 有 ,最有可能的位 为x =


10; 着beta的 ,Pmf 围也会扩大。
图9-2
 用alpha=10和一 的beta 的PMF

9.4
 似然
现在我们 要一个 然 。在给 对手的坐 的情况下,我们可以 用MakeLocationPmf x
的 然度。
    def Likelihood(self, data, hypo):
       alpha, beta = hypo
       x = data
       pmf = MakeLocationPmf(alpha, beta, self.locations)
       like = pmf.Prob(x)
       return like

强调下,alpha和beta是射手的 想坐 ,x是 命中痕迹的位 。

pmf 含了给出射手的坐 时墙上 个位 点的概率。 Pmf我们可以得到 察到的 位 的概率。

大功告成。要更新Suite对象,我们可以 用 承自Suite的UpdateSet。
, ,18 ,21 ])
suite.UpdateSet ([ 15  16 

其结 是一个 射 个(alpha,beta)到一个后 概率的分 。

9.5
 联 分布
分 的 个 都是一个元 变量时, 称为联 分布。 了多个变量的分 ,这 是“ 合”的
含 。 合分 含了变量的分 以 变量 的 。

给 一个 合分 ,我们可以 个变量的独 分 ,这 称为 缘 分 布 ( marginal


distribution)。

thinkbayes.Joint 了 缘分 的 法:
# class Joint:

    def Marginal(self, i):
        pmf = Pmf()
        for vs, prob in self.Items():
            pmf.Incr(vs[i], prob)
        return pmf

i是我们想要的变量的 ,在 示例中i = 0 示alpha分 ,i = 1 示beta分 。

下 是 取 缘分 的 :
    marginal_alpha = suite.Marginal (0)
    marginal_beta = suite.Marginal (1)

图9-3显示了结 (转 为CDFs)。对 alpha,中 是18,就在 察到的 据集的中心附近。对


beta,最可能的 靠近墙壁(<10), 10 外的分 是均 的,这恰好 了在这 可能位
的 据非常不起眼( 可能 不 )。
图9-3
 据后,alpha和beta的后 CDF 线

给 的后 的 缘,我们可以分 为 个坐 :

print 'alpha CI '  marginal_alpha.CredibleInterval(50)

print 'beta CI '  marginal_beta.CredibleInterval(50)

对 alpha,50% ,
为(14 21),beta是(5 31)。 以 据 , 的证据 射手 在 内的近
侧。 这还不是强证据, 为
90% 了 的大部分 域!

9.6
 分布
分 示了有 变量 自的 息, 没有捕捉变量 的依 。

可 其依 的一 法是通过 分布。thinkbayes.Joint 了一个 法:


   def Conditional(self, i, j, val):
       pmf = Pmf()
       for vs, prob in self.Items():
           if vs[j] != val: continue
           pmf.Incr(vs[i], prob)

       pmf.Normalize()
       return pmf
的,i是我们想要的变量的 ;j是调 变量的 ,val是有条件 。

其结 是 i个变量在 j个变量 是val这一条件下的下的分 。

例 ,下 的 alpha在一 beta 围下的分 :


betas = [10, 20, 40]

for beta in betas:
    cond = suite.Conditional(0, 1, beta)

图9-4显示了结 ,我们可以 其 整地 为“条件 缘的后 分 ”(posterior
conditional
marginal


distribution)。

图9-4
 以 个beta 据为条件的,alpha的后 概率分 线

变量是独 的,条件分 就会 。 为 们(条件分 )不 ,我们 此可以说变量是


的。

例 , beta = 10,alpha的条件分 围就 。 对 较大的beta ,alpha的分


围就较宽。

9.7
 置信区间
一 可 后 合分 的 式是 。 我们在 23 讨 “ ”的时 ,我略过
了一个微 息点:对 给 的分 ,有很多 度的 。例 , 你想有一个50%的可
,你可以选择 一 的 起来是50%的概率 。

是一维的,最常 的是选择中心的 ,例 ,中 
50% 含了 25和 75 分


位 的 有 。

在多个维度情况下,什么是 的 并非显 。最好的选择可能要取决 上下 , 一个


常用的选择是最大 然 ,其中 含了 为
50%的最有可能的 ( 一 其他 分 )。

thinkbayes.Joint 了 最大 然 的 法:
# class Joint:

    def MaxLikeInterval(self, percentage=90):
        interval = []
        total = 0

        t = [(prob, val) for val, prob in self.Items()]
        t.sort(reverse=True)

        for prob, val in t:
            interval.append(val)
            total += prob
            if total >= percentage/100.0:
                break

            return interval

一步是在Suite中创 一个 含 有 的 ,以概率 减顺 储。接着 历 , 到


概率直到超过缺省 分 percentage。这一步的结 是 Suite对象得到的 。请 ,这 不一
是 续的。

要可 这 ,我写了一个 ,根据 个 的出现 为 个概率 “着色”:


def MakeCrediblePlot(suite):
    d = dict((pair, 0) for pair in suite.Values())

    percentages = [75, 50, 25]
    for p in percentages:
        interval = suite.MaxLikeInterval(p)
        for pair in interval:
            d[pair] += 1

    return d

d是一个在Suite中 个概率 和其 在 进 射的字 。 环部分的 进 这


并修改d。

图9-5显示了结 。25% 为靠近墙沿的最暗 域。对 更大的 分 , 更大并


向 的右侧。
图9-5
 对手坐 的

9.8
 讨
章的内 说 了 章里 到的贝 架可扩展到 维参 。唯一的 在 , 个
由参 元 来 示。

我还 了 
 Joint
 对 象 , 这 是 一 个 了 合分 法的父类,可用 Marginal ,


Conditional ,还有 MakeLikeInterval 合分 。以 向对象的概念来说, Joint
对象是一个 入对象
( 
http://en.wikipedia.org/wiki/Mixin)。

章中出现了很多新的词 ,让我们来 顾下。

联 分布

示在多维 中 有可能 和 们的概率。 章中的例子是由坐 alpha和beta 构成的 维 。


合分 了 一个(alpha,beta)对的概率。

缘分布

合分 中, 个参 在其他参 未 情况下的分 ,例 图9-3展示的 自独 的alpha分 和beta


分 。
分布

在一个 合分 中。给 一个 多个其他参 条件的情况下, 个参 的分 。例 ,图9-4显示


了alpha在beta的 个不 下的 个分 。

合分 ,可以 出 和条件分 。有了 的条件分 息,可以至少是近 地重 合


分 。 分 不能重新创 合分 , 为 丢 了变量 的 息。

对 个参 都有n个可能的 ,在 合分 中的大多 操 要的是 n2成 的 时 。


还有参 d, 时 nd, 着维 的 , 速地变得不 用。

你要在合 时 内 上 万个 ,这 情况是可 的:2个维度, 个参 有1000个可能


; 3个维度, 个参 100个可能 ; 6个维度, 个参 10个 。

要 更多维度, 个维度上更多 ,可以试试其他的优 。我在 15章 了一个例子。

你可以 http://thinkbayes.com/paintball.py
下载 。更多 息,请参 的“ 指南”。

9.9
 习
练习9-1。

在我们的 型中,对手 向射击都有 的可能。 为练习,我们来 改进这一 型。

章的分 射手最有可能对墙的近端射击。 在现 中, 对手靠近墙壁, 为他不可能看到


自己和墙壁 的目 , 以也不大可能射击到墙上。

一个改进的 型, 这 为 在内。尝试找到一 更真 的 型, 不要太 杂。



第10 
 贝 斯 似

10.1
 假说
我对古 科学有 爱。最近我访问了Norumbega ,这是一个 ·诺顿· 福德 的不
纪念 , 是双效发 和赝 的发 。不过这不是 章要讨 的。

章是 变异 说,

“最早在19 纪 ,约 · 克 为男 的能 围大 女 ,尤其在 上。 说,他


天 和弱 人口中,男 占 大多 。 克 断 女 缺少变异 是较为 的 现, 以他
得男 是‘优越生物’。”

来自http://en.wikipedia.org/wiki/Variability_hypothesis。

我尤其 最后那部分, 为我怀 , 事 能证 女 的变异 上更大, 克 也会 这


为较 的 志。无 ,你总能 到变异 说的证据站不住脚的说法。

不过,最近我在 上 查来自CDC的危 监 统(BRFSS)的 据,尤其是自我 交的成年美


国男 和女 的 度 据时,也 到了这个问题。 据集 了154407 男 和254722 女 。以下是
我们的发现:
 

男 平均 为178 米;女 平均 为163 米, 以 平均 看男人 大,这毫不 。


男 据的 准 差是7.7 米;女 是7.3 米, 此, 对 上看,男 的变异 更大

是为了 较 据的变异 , 用变异 (Coefficient
of
Variation,CV)更有 , 准
差除以平均 。 对 刻度 ,这是变异 的一个量 无 的 量 。对 男 CV为0.0433;对
女 CV是0.0444。

这就很靠 了, 以我们可以得出结 ,此 据集 了有 的证据反对变异 说。 是我们还可


以用贝 法得到更 的结 ,在 这个问题的过 中,我还有 会来 示一 大 据集的

我以下 个步 进 :

1.我们先 最 的 现开始,不过 用 小 1000个 的 据集。

2.通过对概率进 对 变 ,我们可以扩展到 量 据集, 会变 。

3.最后,我们以近 贝 快 过 , 也 称 为 ABC ( Approximate
 Bayesian


Computation)。

你可以 http://thinkbayes.com/variability.py下载 章中的 。 了 更多 息,请参 的“


指南”。

10.2
 值和标准差
在 
9
章我们通过 合分 时 了 个参 。在 章中,我们用 的 法来 分 的参
:均 mu, 准差sigma。

就这个问题,我 了一个 为height的Suite对象,其 示 一个mu,sigma对到其概率的 射:


class Height(thinkbayes.Suite, thinkbayes.Joint):

    def __init__(self, mus, sigmas):
        thinkbayes.Suite.__init__(self)

        pairs = [(mu, sigma) 
                  for mu in mus
                  for sigma in sigmas]

        thinkbayes.Suite.__init__(self, pairs)

mus 是 mu 的一个 ;sigmas的是sigma 的一个 。 有mu,sigma 对的先 分 是一个均 分


然 得出, 到mu和sigma的 ,我们 一个 x的 然度。EvalGaussianPdf


的 用,就是这个, 此我们要做的就是 用 :
# class Height

    def Likelihood(self, data, hypo):
        x = data
        mu, sigma = hypo
        like = thinkbayes.EvalGaussianPdf(x, mu, sigma)
        return like

学的 度学习过统 学,你 道 进 PDF 时得到的是概率密度。为了得到一个概


率,你必须在一 围上对概率密度积分。

就我们的目的来说,我们其 不 要概率,只是 要一 概率的量,概率密度就 合


。这个问题最 的部分是选择mus和sigmas的合 围。 围太小,会 略了一 得 的概率
,导 得到 误结 。 围太大, 管可以得到 的 案, 是白白 了 能 。

以在这里有 会利用 的 法,让贝 法更 效。 体说,我们可以用 的 量找


到mu和sigma的最可能位 ,并利用这 的 准误差来选择一个可能的 围。 分 的 参 是μ
和σ,我们取n个 的一个 ,μ的 量就是 的均 m。

σ的 量是 的 准 差,s。

对μ的 的 准误差为 , 对σ的 的 准误差为 。

下 就是 有 的 :
def FindPriorRanges(xs, num_points, num_stderrs=3.0):

    # compute m and s
    n = len(xs)
    m = numpy.mean(xs)
    s = numpy.std(xs)

    # compute ranges for m and s
    stderr_m = s / math.sqrt(n)
    mus = MakeRange(m, stderr_m)

    stderr_s = s / math.sqrt(2 * (n-1))
    sigmas = MakeRange(s, stderr_s)

    return mus, sigmas
xs是据集。num_points是取 围内 的 的个 。num_stderrs是 量 侧 围的宽度,以
准误差 。

是mu和sigma 对构成的一个 。

MakeRange 下:
def MakeRange(estimate, stderr):
    spread = stderr * num_stderrs
    array = numpy.linspace(estimate-spread,
                           estimate+spread,
                           num_points)
    return array

numpy.linspace 创 一个由 距分隔的元 构成的 ,在 estimate-spread 和 estimate+spread


上, 右 端的 。

10.3
 更新
最后,下 是创 和更新Suite对象的 :
mus, sigmas = FindPriorRanges(xs, num_points)
suite = Height(mus, sigmas)
suite.UpdateSet(xs)
print suite.MaximumLikelihood()

根据 据来选择先 分 的 围,接着 利用这 据 做了更新,这个过 多少有 。通常


来说, 利用了 的 据,事 上的 是 。

在这个例子里是可以的。的 ,我们用 据来选择先 的 围, 这只是为了 免 量很大、


却微 其微的概率。给 num_stderrs = 4, 围就 以 有 得 的 然度了, 后 扩
大 围对结 也毫无 。

上, mu和sigma 的 有 上,先 都是均 分 的, 为了 效率我们 略了 有不重要的


10.4
 CV的后验分布
一 有了mu和sigma的后 合分 ,我们就可以 出男女的CV分 ,自然地,其中一个的概率会
超过 外一个的概率。

为了 CV的分 ,我们枚 mu和sigma的 对:


def CoefVariation(suite):
    pmf = thinkbayes.Pmf()
    for (mu, sigma), p in suite.Items():
         pmf.Incr(sigma/mu, p)
    return pmf

然后我们用thinkbayes.PmfProbGreater来 男 有更多变异 的概率。

分 很 , 还有 个额外的我们必须 的问题。

1. 着 据集大小的 ,我们 到了一 由 浮点 带来的 问题。


2. 据集 含了一 不对的 端 。我们 要让 过 在 到这 异常 时也是 壮
的。

以下 这 问题 其 决 案。

10.5
 据下
BRFSS 据集选择 100个 进 我 说的分 , 会 常, 得到看起来合 的
后 分 。

我们选择 1000个的 ,然后 ,我们 Pmf.Normalize得到一个 误:


ValueError :total probability is zero.

这个问题在 我们 用概率密度来 然度, 续分 密度往往很小。 你 1000个 ,


其结 是非常小的。在这个例子里,其 甚至小到不能由一个浮点 来 示, 以 向下 入到 ,这
称为下 。 分 的 有概率是0,也就不 成其为一个分 。

一 可能的 决 案是 更新后重新归一 Pmf, 100个 ,这 就 常了, 很


一个更好的选择是以对 变 来 然度。这 一来就不是 较小 , 是 对 了。


Pmf 了Log、LogUpdateSet和Exp 法, 这个过 变得 。

Log Pmf中概率的对 :
# class Pmf

    def Log(self):
        m = self.MaxLike()
        for x, p in self.d.iteritems():
            if p:
                self.Set(x, math.log(p/m))
            else:
                self.Remove(x)

在应用Log进 对 变 , 用MaxLike找到m——Pmf中最 的概率 。 有概率除以m, 以最


概率 归一 为1,这 得到一个为0的对 。其他日志概率均为负 。 Pmf中有 的概率为
0,去 们。

然 Pmf是基 对 变 的,我们不能 用 Update 、 UpdateSet Normalize 。 则其结 没有


; 你这么用,Pmf会 发异常。 反,我们必须 用LogUpdate和LogUpdateSet。

下 是LogUpdateSet的 现:
# class Suite

    def LogUpdateSet(self, dataset):
        for data in dataset:
            self.LogUpdate(data)

LogUpdateSet 历 据并调用LogUpdate:
# class Suite

    def LogUpdate(self, data):
        for hypo in self.Values():
            like = self.LogLikelihood(data, hypo)
            self.Incr(hypo, like)

LogUpdate类 Update,不 的是 调用Loglikelihood 不是Likelihood,Incr 不是Mult。

用对 然 免了下溢的问题, 时Pmf只是进 对 变 ,没有更多 用了。我们还必须 用


Exp来转 这一变 过 :
# class Pmf

    def Exp(self):
        m = self.MaxLike()
        for x, p in self.d.iteritems():
            self.Set(x, math.exp(p-m))

对 然度是一个大的负 ,得到的 然 有可能下溢。 以Exp寻找对 然度的最大 m,


用m转 有的 然 (非对 )。得到的分 有1的最大 然度。这个过 以最小的 度 转 了
对 变 。

10.6
 对 似然
现在我们 要的是Loglikelihood。
# class Height

    def LogLikelihood(self, data, hypo):
        x = data
        mu, sigma = hypo
        loglike = scipy.stats.norm.logpdf(x, mu, sigma)
        return loglike

norm.logpdf PDF的对 然 。

下 是整个更新过 :
    suite.Log ()
    suite.LogUpdateSet (xs)
    suite.Exp ()
    suite.Normalize ()

顾一下, Log Suite对象进 对 转 。 LogUpdateSet 调用 LogUpdate , 调用 Loglikelihood 。


LogUpdate 用Pmf.Incr, 为 对 然 然度 。

更新后,对 然都是较大的负 , 以在进 变 转 ,Exp对 们进 转 ,这就是我们 免


下溢的过 。

一 
suit
对象 转 来,概率就变 “线 ”的,这 着其“非对 ”了, 以我们可以 用


Normalize。

用这 法,可以在 整个 据集时 免产生下溢, 然很 。我的 脑 起来可能 要


一小时。我们还可以做得更好。

10.7
 一个小的优
通过 学和 的优 倍地 快了速度。 下一 了一 还要更快的 法。 以, 你
想直接得到好 法,那么可以 过这一 。

Suite.LogUpdateSet在 个 据点上调用LogUpdate一 。我们可以通过 一 整个 据集的对


然 来 快步 。

我们 开始 的PDF:

并 对 log(去 了常 项):

对 给 的 xi,总对 然是

去 不 i的项,得到

这一过 转 为Python 下:
# class Height

    def LogUpdateSetFast(self, data):
        xs = tuple(data)
        n = len(xs)

        for hypo in self.Values():
            mu, sigma = hypo
            total = Summation(xs, mu)
            loglike = -n * math.log(sigma) - total / 2 / sigma**2
            self.Incr(hypo, loglike)

这只是一个小的优 , 带来了一个更大的优 可能 。请 , 和只取决 mu , 不是


sigma, 以对mu的 一个 我们只 要 一 。

为了 免重新 ,我分 出一个 总和的 ,并memoize , 其在字 中 储 的 结


( http://en.wikipedia.org/wiki/Memoization):
def Summation(xs, mu, cache={}):
    try:
        return cache[xs, mu]
    except KeyError:
        ds = [(x-mu)**2 for x in xs]
        total = sum(ds)
        cache[xs, mu] = total
        return total

储先
cache 的总和。 可能try语 cache中 一个结 , 则 总和, 缓 并
结 。
唯一美中不 的是,我们不能用 为缓 中的一个key, 为 不是一个哈希类型。这就是为什
么LogUpdateSetFast 据集转 为一个元 。

这 优 以大约100的 快了 ,在我不 快的 上 整个 据集(154
407 男 和


254
722 女 )用了不到一分 。

10.8
 ABC( 似贝 斯 )
是,也许你耗不起这 的时 。这时 ,近 贝 (ABC)就是合 的 法了。ABC 后的
动 是, 据集的 然度有以下 点。

1. 非常小, 是对 大型 据集来说,这就是为什么我们必须 用对 转 形式的原 。

2. 开销大, 以我们不得不做这么多的优 。

3. 并非我们 要 的。

我们并不真 心看到 一 据集的 体 然度。尤其对 续变量,我们 心的是 到一个


类 据的 据集的 然度。例 ,在欧元问题上,我们不 心 币翻转的顺 ,只 心 和反
的总 。 在 问题上,我们不 心看到 一个 体的 , 是 的 量和 的最大

,BRFSS的 中,我们并不真想 道看到 一个 据 集合的概率( 是 为有成 上万的


人), 是更类 出这 的问题“ 体人口中取出一个参 为μ和σ的10万人口 ,那么取到
一个符合 均 和 差的 的 会是多少?”

对 一个 分 的 , 为可以分 地找到 分 的统 量,我们可以有效地 这个问


题。在 先 分 的 围时,我们 做到了这一点。

参 为μ和σ的 分 取n个 ,并 均 m,m的分 是参 为μ和 的 分


地, 的 准差分 s,也是为参 和 的 分 。

给 μ和 σ ,我们可以 用这 的分 来 统 量m和s的 然度。下 是


LogUpdateSet 现这个功能的新 :
def LogUpdateSetABC(self, data):
    xs = data
    n = len(xs)

    # compute sample statistics
    m = numpy.mean(xs)
    s = numpy.std(xs)

    for hypo in sorted(self.Values()):
        mu, sigma = hypo

        # compute log likelihood of m, given hypo
        stderr_m = sigma / math.sqrt(n)
        loglike = EvalGaussianLogPdf(m, mu, stderr_m)

        #compute log likelihood of s, given hypo
        stderr_s = sigma / math.sqrt(2 * (n-1))
        loglike += EvalGaussianLogPdf(s, sigma, stderr_s)

        self.Incr(hypo, loglike)
在我的 脑这个 整个 据集用时大约1 ,得到的结 有5位 的 度 结 一 。

10.9
 的可
我们 差不多可以看到结 了, 还有一个问题要 。 据集中有一 是 误的异常
据 。例 ,有3个男人 为61
 米,也就是说他们是 界上最 的成年人了。 外,有四个 229
米的女 ,这个 据 界上最 的女人 一点。

这 也不是 没可能, 还是有点不 的,这 让 这 有 度。 我们必须


得 , 为这 端 对 变异 问题有不成 例的 。

由 ABC基 总统 , 不是整个 据集,我们可以选择在有异常 的情况下也 的 总统 量


这一过 更可 靠。 例 ,我 们可以不 用 平均 和 准 差 , 用中位 和四分位 距
(IQR), 在 25和 75个 分位 。

更一般地,我们可以 出一个分 有 的 分位 距(IPR):


def MedianIPR(xs, p):
    cdf = thinkbayes.MakeCdfFromList(xs)
    median = cdf.Percentile(50)

    alpha = (1-p) / 2
    ipr = cdf.Value(1-alpha) - cdf.Value(alpha)
    return median, ipr

xs是一个 ,p是 希望的 围;例 ,p = 0.5产生四分位 距。

MedianIPR的工 原 是 xs的CDF,然后 取中位 和 个 分位 的差。

通过 CDF 给 准差的分 的 分 ,我们可以 ipr转 到一个sigma的 。例 ,一


个 的 则是, 分 的68% 入均 的一个 准差内,在 右端 下了其余的16%。
我们在 16和 84 分位 的 围内进 ,我们 期的结 是2*sigma, 以我们可以通过
68%的IPR 除以2来 sigma。

更一般地,我们可以选择sigma的个 。MediaS 了这一 的更通用的 :


def MedianS(xs, num_sigmas):
    half_p = thinkbayes.StandardGaussianCdf(num_sigmas) - 0.5

    median, ipr = MedianIPR(xs, half_p * 2)
    s = ipr / 2 / num_sigmas

    return median, s

,xs是 ;num_sigmas是结 决 的 准差 量。其结 是median,μ的 ;还有s,


σ的 。

最后,在LogUpdateSetABC我们可以用median和s 平均 和 准差,效 很好。

这 有点儿 ,我们 在 用 察的 分位 μ和σ, 是贝 法灵活 的一个示例。


上,我们一直都在问“给 一个μ和σ的 ,还有一个有可能 入 误的 过 ,那么生成一
给 统 的 然度是多少?”

我们可以不受 地选择 顺眼的 统 量,此时:μ和σ 了分 的位 和 , 以我们


要选择那 现了这 征的统 量。例 , 我们选择了 49和 51 分位 ,有 分 围的
息就很少(译 :太 ), 以 得对σ的 对 据的约束小。就生成的 , 有sigma的可
能 都 然度, 以西格 的后 分 看起来就和 分 没有 。

10.10
 的 更大?
我们 可以 开 的问题了:男 的变异 女 更大 ?

通过 用基 中位 和IPR的ABC 法, num_sigmas = 1,我 了mu和sigma 合分 的后 。


图10-1和图10-2显示了结 的 线图,mu在x ,sigma在y ,概率以z 示。

图10-1
 美国男 平均 和 准差后 合分 的 线图


图10-2
 美国女 平均 和 准差后 合分 的 线图

对 一个 合分 ,我 了CV的后 分 。图10-3显示了男 和女 的这 分 结 。男 平
均 为0.0410;女 的平均 为0.0429。由 没有重 ,我们可以 较 地得出女 在
男 变异 更大的结 。
图10-3
 男 和女 变异 CV的后 分 CDF 线,基 可靠型

那么,这就是变异 的最 案了?可 的是,没有。事 证 ,这 的结 依 跨 分


围的选择。指 num_sigmas = 1,我们可以得出结 说女 波动 围更大, 若是指 num_sigmas = 2,
在 度下,结 是男 围更大。

这一差 的原 在 , 小 材的男人更多, 平均 也较大。

此,我们对变异 的 取决 对“变异 ”的 。指 num_sigmas = 1时,我们 接近


平均 的人。 大num_sigmas,就给 了 端 更多的 重。

选择究竟要 出问题的 一 ,我们就 要对这一 更 的 。 为 此,变异 可能


煳到 以 。

然 ,这有助 说 我的一 新想法, 我想你会 可,这是一个有 的例子。

10.11
 讨
还有 对ABC的看法。一 是, 称 指的,和 用 的 ,近 法 起来
更快。
请记住,贝 分 总是基 型决 的,这 着不 在“ ”的 决 案。 人 的物
统都可能 在许多 型, 个 型产生不 的结 。要对结 进 ,就必须 型。

此,ABC的 一 是, 然度的 外一类 型。 p(D|H),我们 出的问题是“在


一个给 下, 据的 然度是多少?”

对 大型 据集, 据的 然度非常小,这 上 的问题可能就不合 。我们真 想 道的结 是


新的 据类 据的可能 , 这里,“类 ”的 是一个 决 。

ABC 后的基 想是, 个 据集产生了 的描 统 量,那 们就是类 的。 在


情况下, 在 章的例子中,到底选择 总统 量并不 显。

你可以 http://thinkbayes.com/variability.py下载 章中的 。 了 更多 息,请参 的“


指南”。

10.12
 习
练习10-1。

“ 效 应 量 ( effect
 size ) ” 是 一 个 在 量 的 差 异 的 统 量 (
http://en.wikipedia.org/wiki/Effect_size)。

例 ,我们可以 用 BRFSS得到的 据去 男 女 的 度差异。由μ和σ的后 分 的


,就能生成这一差异的后 分 。

用效应量的无量 度量 法可能更好, 不以 米为 位进 差异 量。一 选择是通过 其


( 据)除以 准差(类 我们用变异 一 )。

1的参 为(μ1,σ1), 2的参 为(μ2,σ2),

无量 的效应量就是

编写一个 , 接收 据的mu和sigma的 合分 ,并 效应量的后 分 。

示: 枚 个分 有 对的时 太 ,应 。

第11 
 假设 验

11.1
 回到

27
 的“欧元问题”中,我 了来自麦凯《 息、 、 和学习 法》中的一个问题:

2000年1月4日星期 ,《 报》上 载了一个统 的 :

以 缘转动 利时一欧元 币250 时,得到的结 是 140 反 110 。“这看起来很可


”,伦敦 学 的统 讲 巴里· 说,“ 币是均 的,得到这个结 的可能
7%”。

那么,这一结 是 为“ 币 心 非均 ” 了证据呢?

我们 了 币 朝上的概率, 我们并没有真 麦凯的问题: 据是 证了 币是 心


的?

在 
4
章中我 出, 据在 一 下 外 下的可能 要 ,那么 据就是支


的,这 贝 子大 1的情况。

在欧元问题的例子中,我们 个 : 用F 示 币是 心的 ,B 示 币是均 的

币是均 的, 据的 然度,p(D
|
F)。 上,我们 成了一个 现这个



def Likelihood(self, data, hypo):
    x = hypo / 100.0
    head, tails = data
    like = x**heads * (1-x)**tails
    return like

我们可以创 一个调用Likelihood的Euro
suite对象:
suite = Euro()
likelihood = suite.Likelihood(data, 50)

p(D|F)是5.5×10−76,这一结 除了说 据集的概率 小,没有什么用 。 要 得 个


然度 们的 率, 以我们还要 p(D|B)。

要 B的 然度并不 , 为“ 心”的含 并不那么 。

一 可能 是在 先 查 据。那么在这个例子里,“ 心”就是指 向上的概率为


140/250。
actual_percent = 100.0 *140/250
likelihood = suite.Likelihood(data, actual_percent)

B的这个 我称 为 B_cheat ; b_cheat 的可能 是34×10−76 , 然 是6.1。 此,我们可以


说, 据是支 这个 的B 的。
用 据来 的 显然是有 的。根据这一 , 据集都 支 B,除非
察到的 向上 分 恰好是50%。

11.2
 来一个公 的对
为了 现一个 的对 ,我们必须在无 据的情况下先 B。那么我们来尝试一个不 的
。 查 利时欧元 币,你可能会 到“ ” “反 ”更 出。可以猜想,形状对x有一 的
, 不能 是 就是这一 让 多 少一点。 以,你可能会想:“我 为 币 心, 以x
是0.6 0.4, 不 道究竟是多还是少。”

我们可以好好 下这个由 个子 构成的 称为B_two的 。我们可以 出 个子


的 然度,然后 平均 然度。

like40 = suite.Likelihood (data 40)

like60 = suite.Likelihood (data 60)
likelihood= 0.5 * like40 + 0.5 * like60

对 b_two 然度 ( 贝 子)为1.3,这 着 据 微弱的证据支 b_two。

更一般地, 想你怀 币就是 心不均 的,可是对 
x
的 没有线 。在这 情况下,你可以创


一个称为b_uniform的Suite对象, 0到100的子 。
b_uniform =Euro(xrange (0  ,101))
b_uniform.Remove (50)
b_uniform.Normalize ()

我以 0到100 始 b_uniform。 除了x 50%的子 , 为 x为50%时, 币就是均 的,不


管你 不 除除这一 ,对结 都没有 
。

要 b_uniform的可能 ,我们 个子 的 然度,并 其 平均 。


def SuiteLikelihood(Suite, data):
    total = 0
    for hypo, prob in Suite.Items():
        like = suite.Likelihood(data, hypo)
        total += prob * like
    return total

b_uniform的 然 是0.47,这 着 F, 据对b_uniform只 是微弱的证据。

你 下SuiteLikelihood的 ,你可能会 到这类 一个更新过 。来 一下,下


是Update的功能:
    def Update(self, data):
        for hypo in self.Values():
            like = self.Likelihood(data, hypo)
            self.Mult(hypo, like)
        return self.Normalize()

Normalize 下:
def Normalize(self):
    total = self.Total()

    factor = 1.0 / total
    for x in self.d:
        self.d[x] *= factor

    return total
Normalize的 是Suite对象中以先 的概率 的总概率 , 子 的平均 然度。Update
续 这个 , 以不用对SuiteLikelihood进 ,我们就可以像下 这 b_uniform的 然度:

likelihood= b_uniform.Update(data)

11.3
 三角前验
在 4章中,我们还讨 了形 三 的 分 ,其在50%附近的 有更 的概率。 子 的
先 分 为三 ,可以这 的 然度:
b_triangle = TrianglePrior()
likelihood= b_triangle.Update(data)

和 F ,b_triangle的 然 为0.84。 以我们可以说 据对 B只 是微弱的证据。

下 显示了 的可能 的先 概率,以 对 F的 然 ( 贝 子)。



     

假设  似然 (×10 −76) 贝 斯因子 


     
 F 5.5  — 
     
 B_cheat 34  6.1 
     
 B_two 7.4  1.3 
     
 B_uniform 2.6  0.47 
     
 B_triangle 4.6  0.84 

根据我们选择的 , 据会对“ 币是 心的” 支 反对的证据, 在 情况下,证据都


是 对微弱的。

综上 ,我们可以用贝 来 较F和B的 然度, 必须做一 工 来 指出 B的


含 。这一点依 币和 币旋转 为的 景 息, 以对 的 ,人们都有 由 出异 。

我就这个例子的 延续了大 ·麦凯的讨 ,得到了一 的结 。你可以


http://thinkbayes.com/euro3.py
下载 章 。 了 更多 息,请参 的“ 指南”。

11.4
 讨
对 B_uniform,贝 子为0.47,和F对 ,这 着 据 的证据反对这一 。在 的部
分中,我 这一证据描 为“弱”, 没有说 原 。

部分原 有 年 。哈 德· 里 ,贝 统 的早期支 , 出了一个 读贝 子的


度:

   
贝 斯因子   
   

1~3  不 一  
   

3~10  可 的 
   

10~30  强 
   

30~100  很强 
   
>100  决 的 

在 例中,支 B_uniform的贝 子是0.47, 以支 F的贝 子是2.1,也就是 里 为


的“不 一 ”,其他的学 也 出了不 的用词。若要 免这 形 词上的 ,我们可以用 率来

你 的 率是1:1,接着你看到了贝 子为2的证据,你 率的后 就是2:1。在概率 ,


据 你的 念度(degree
of
belief) 50%改变到66%。 对 大多 现 界的问题来说,这一类
误差和其他不 来 导 的 要小 。

一 情况下, 你得到一个贝 子是100的证据,你的后 率 是100:1 99%以上。无


你是 ,这 的证据是“决 的”,是 强烈的证据。

11.5
 习
练习11-1。

有 人 感(ESP)的 在。例 ,有 人猜扑克牌的能 进 猜 要 。

在这类ESP上,你的 度是什么?你 为 可能 在还是不 在?还是你强烈 呢?写下你


的先 率。

现在, 能说服你 ESP至少有50%可能 在的证据强度。多大的贝 子能让你90% ESP


的 在?

练习11-2。

想 一个问题的 案是1000。也就是说,一个贝 子是1000的支 ESP的证据 可以改变你的


想法。现在 你在一个 威 审科学期 上读到了一篇 , 中 出了一个贝 子是1000的支
ESP的证据,这会改变你的想法 ?

没有,你怎么 决这个 显的矛盾?你会发现 读大 ·休谟的 章《 迹》会帮助你 这个


问题。 章 http://en.wikipedia.org/wiki/Of_Miracles。

第12 
 证据

12.1
 读SAT成
你是 诸 一个工 学 的 生 , 在 个 选人爱丽 和 ,他们在许多
的 历都差不多,只是爱丽 在SAT 学部分的得分更 。SAT是 在 量大学 平 学准 情况的 准
试。

爱丽 得到了780分, 得到了
740
分( 分800分),你也许想 道这一差异是 就是爱丽


准 得更好的证据,还有证据的强度是多少。

现 中,这 个分 都非常好, 位 选人可能都为大学 学学习做好了准 。 以真 的


可能会 我们选择那 最能体现我们希望学生 的 能和态度的 选人。不过既然这是一个贝
的例子,我们还是 住不要扩大问题 畴, :“爱丽 准 得更好的证据有多强?”

要 这个问题, 要进 一 决 。我 以一个其 不真 的 开始,然后 来改进


型。暂时的,先 有的SAT试题有 度。事 上,SAT 选择的试题是有一 度 的,
为这 了度量 题 统 差异的能 。

是, 我们选择一个 部试题有 度的 型,就可以为 个参 试 一个 征


p_correct, 对 一问题的概率。这 可以很 地 出给 得分的 然度。

12.2
 得分SAT
为了 SAT成 ,我们要了 得分和 例分 的 过 。 个 试 基 对题和 题的 量会得
到一个原始分 。原始得分 转 为200~800 的 例分 。

2009年,SAT 学部分有54题,原始分 为 个 试 对题的个 减去 题的个 以1/4分


( , 对1题得1分, 1题减1/4分)。

负责管 SAT的 事会,发 了一个 原始分 到 例分 的 射图。我下载了 据并 其封


在一个插 对象中, 能进 向( 原始分 到 例分 )和反向( 例分 到原始分 )查找。

你可以 http://thinkbayes.com/sat.py下载这个例子的 ,更多 息请参 的“ 指南”。

12.3
 先验
美国大学 事会还发 了 有 试 例分 的分 。 我们 一个 例分 转 为原始分 ,
并除以题目 量,那么结 就是p_correct的 。 以我们可以 用原始分 的分 为p_correct的先
分 。

下 是读取并 据的 :
class Exam(object): 

    def __init__(self): 
        self.scale = ReadScale()
        scores = ReadRanks()
        score_pmf = thinkbayes.MakePmfFromDict(dict(scores)) 
        self.raw = self.ReverseScale(score_pmf) 
        self.prior = DivideValues(raw, 54)

Exam封 了我们 的有 试的 息。ReadScale和ReadRanks读取 件并 含了 据的一个对


象:self.scale是转 原始分 到 例分 ( 反)的Interpolator;scores是(得分, 率)对的

score_pmf 是缩 分 的Pmf对象。self.raw 是原始分 的Pmf对象。 self.prior是p_correct 的Pmf对


象。

图12-1显示了p_correct的先 分 。这 分 近 分 , 是 在 端很平。在 上,SAT


强调了平均 个 准差内的 试 得分, 略超出 围的部分。

图12-1
 SAT 试 生p_correct的先 分

对 一个参 试 ,我 了一个 为Sat的Suite对象, p_correct的分 。 下:


class Sat(thinkbayes.Suite): 

    def __init__(self, exam, score): 
        thinkbayes.Suite.__init__(self) 
        self.exam = exam
        self.score = score

        # start with the prior distribution
        for p_correct, prob in exam.prior.Items():
            self.Set(p_correct, prob) 
        # update based on an exam score
        self.Update(score)

__init__接收一个Exam对象和 例分 。 创 一个先 的 , 根据 试成 更新这个 。

像往常一 ,我们 Suite 承Update, 改写Likelihood:


def Likelihood(self, data, hypo): 
       p_correct = hypo
       score = data

       k = self.exam.Reverse(score) 
       n = self.exam.max_score
       like = thinkbayes.EvalBinomialPmf(k, n, p_correct) 
       return like

hypo是p_correct的一个 ,data为 例分 。

为了 起 ,原始分 就是 案的 量, 略 误 案的罚分( 题1/4分)。这 的 , 然度


由 n个试题中得到k个 的概率的 项分 给出。

12.4
 后验
图12-2显示了在爱丽 和 分 基础上得到的p_correct的后 分 。我们可以看到, 们重 在
一起,有可能 的p_correct更 , 不可能。
图12-2
 爱丽 和 的p_correct的后 分

我们 到原来的问题,“有多强的证据 ,爱丽 准 得更好?”我们可以用p_correct的后


分 来 这个问题。

要以贝 的形式 问题,我 了 个 :


 

A:p_correct上,爱丽 。
B:p_correct上, 爱丽 。

要 A的 然度,可以 后 分 中枚 有 对, 得到 有爱丽 的p_correct


概率总和,我们 有一个 thinkbayes.PmfProbGreater来 现 。

此,我们可以 一个 A和B的后 概率的Suite对象:


class TopLevel(thinkbayes.Suite): 
    def Update(self, data): 
        a_sat, b_sat = data

        a_like = thinkbayes.PmfProbGreater(a_sat, b_sat) 
        b_like = thinkbayes.PmfProbLess(a_sat, b_sat) 
        c_like = thinkbayes.PmfProbEqual(a_sat, b_sat) 

        a_like += c_like / 2
        b_like += c_like / 2

        self.Mult('A', a_like) 
        self.Mult('B', b_like) 

        self.Normalize()

通常, 我们 一个新的Suite对象时,会 承Update,并(根据 型) 现Likelihood。 例中,


则 要重写Update, 为这 能更 时 的 然度。

到Update的 据是 示了p_correct后 分 的Sat对象
。

a_like是爱丽 较 的p_correct的总概率;b_like是 较 的p_correct的总概率。

c_like 是 “ ”的概率,在 用一 散 为p_correct 的情况下,这 就是人为的


了。 为, 我们 用更多的 ,c_like会较小,在 端情况下, p_correct 是 续的,c_like 为
。 以我 
c_like 为一 入误差并 在a_like和b_like 的 去。

下 的 创 了TopLevel并更新 :
exam = Exam()
    a_sat = Sat(exam, 780) 
    b_sat = Sat(exam, 740) 

    top = TopLevel('AB') 
    top.Update((a_sat, b_sat)) 
    top.Print()

A的 然度是0.79,B的 然度为0.21。 然 ( 贝 子)为3.8,这 着这 试成 的证据


,在SAT成 上,爱丽 优 。看到 试成 , 我们 A和B可能 ,那么在看到成
后,我们应 A的概率是79%,这 着 然有21%的可能, 准 得更好。

12.5
 一个更好的模型
请记住,我们 今 做的分 都是基 有SAT问题是 度的 下的。 上,有 题 其他
题要 ,这 着爱丽 和 的差异可能会更小。

是这有多大的 误差? 误差小,我们可以得出 一个 型( 度) 好的结 。


误差大,就 要一个更好的 型。

在接下来的 中,我们开发了一个更好的 型,并 会发现( 一下) 误差就是小的。


以, 你 型,可以 过这 内 直接到下一章。 你想了 更真 的 型 过 ,接着
往下看……
 

个 试 有一 度的 题效率efficacy, 题效率 量其 SAT问题的能 。


个问题有不 平的 度difficulty。
最后, 一个 试 问题的 会 题效率efficacy和 度 平difficulty ,并由下
决 :
def ProbCorrect(efficacy, difficulty, a=1): 
    return 1 / (1 + math.exp(-a * (efficacy - difficulty)))

此 是 项 响 理 的 线 的 一 个 , 你 可 以 参
http://en.wikipedia.org/wiki/Item_response_theory。 题效率和 度 平基 一刻度 平,得到 案
的概率就只取决 们 的差异。

efficacy和difficulty 时, 的 问题的概率为50%。 efficacy ,概率接近100%,


降 ( diffiulty ),概率接近0%。

题 在效率上的分 和 有问题 度的分 ,我们就可以 原始分 的 期分 。我们 通


过 步 成。首先,对 efficacy的 个 题 ,我们 原始分 的分 下:
def PmfCorrect(efficacy, difficulties): 
    pmf0 = thinkbayes.Pmf([0]) 

    ps = [ProbCorrect(efficacy, diff) for diff in difficulties] 
    pmfs = [BinaryPmf(p) for p in ps] 
    dist = sum(pmfs, pmf0) 
    return dist

difficulties是 度 , 一个试题对应一个 度 。ps为概率的 ,pmfs是这 个 的Pmf对


象 。下 是对应的创 :
def BinaryPmf(p): 
    pmf = thinkbayes.Pmf()
    pmf.Set(1, p) 
    pmf.Set(0, 1-p) 
    return pmf

dist是这 Pmfs的总和。还记得40 我们 Pmf对象时的“ ”,结 是总和的分 。为了 用


Python的sum 来 Pmfs,我们 要 pmf0 为Pmfs的 , 以pmf + pmf0
就 pmf了。

道 题 的效率,我们可以 他们原始分 的分 。对 一群有不 的 题效率的人, 产


生的原始分 的分 是 合的。下 是 合分 的 :
# class Exam: 

    def MakeRawScoreDist(self, efficacies): 
        pmfs = thinkbayes.Pmf()
        for efficacy, prob in efficacies.Items():
            scores = PmfCorrect(efficacy, self.difficulties) 
            pmfs.Set(scores, prob) 
        mix = thinkbayes.MakeMixture(pmfs) 
        return mix

MakeRawScoreDist接收efficacies ,这是一个 示 有 题 效率分 的Pmf对象。我 是均


为0, 准 差1.5的 分 。这一 。得到一个问题的 的概率取决 题效率和试题
度的 , 以我们可以选择效率的 位, 准 应的题目 度的 位。

pmfs是 含 一 题效率Pmf的一个元Pmf,并 射到 一 的 试 上。MakeMixture接收元


Pmf并 合的分 (参 45 上的“ 合分 ”)。

12.6
 校准
我们 度的分 情况,我们就可以 用 MakeRawScoreDist 原始分 的分 。 对 我们来
说,问题是类 的其他 法:有原始分 的分 ,要 断 度的分 。
 度的分 是带有参 center
和width的均 分 ,MakeDifficulties可以得到这 参 下试题 度的 。
def MakeDifficulties(center, width, n): 
    low, high = center-width, center+width
    return numpy.linspace(low, high, n)

通过尝试了 个 合,我发现,center=
−0.05和width=
1.8得到的原始分 分 类 据,
图12-3 示。
图12-3
 原始分 的 分 和一个拟合 的 型

此, 度的分 是均 分 ,其 围大约是−1.85至1.75, 题效率是均 为0, 准 差1.5的


分 。

下 显示了不 效率 的 试 ProbCorrect的 围:

  (Difficulty) 
 答 效 (Efficacy) 
 −1.85   −0.05   1.75 
 3.00   0.99   0.95   0.78 
 1.50   0.97   0.82   0.44 
 0.00   0.86   0.51   0.15 
 −1.50   0.59   0.19   0.04 
 −3.00   0.24   0.05   0.01 

效率为3的 题 ( 个 准差 平均 )有99%的 会 对最 的问题,78%的 会 对最 的


问题。在 的 一端, 均 个 准 差的 题 ,只有24%的 会 对最 的问题。

12.7
 效 的后验分布
现在, 型 准了,我们可以为爱丽 和 题效率的后 分 。下 是一个 用
型的Sat类的新 :
class Sat2(thinkbayes.Suite): 

    def __init__(self, exam, score): 
        self.exam = exam
        self.score = score

        # start with the Gaussian prior
        efficacies = thinkbayes.MakeGaussianPmf(0, 1.5, 3) 
        thinkbayes.Suite.__init__(self, efficacies) 

        # update based on an exam score
        self.Update(score)

Update调用Likelihood,这 出 SAT得分时, 题 效率 平的 然度。


def Likelihood(self, data, hypo): 
     efficacy = hypo
     score = data
     raw = self.exam.Reverse(score) 

     pmf = self.exam.PmfCorrect(efficacy) 
     like = pmf.Prob(raw) 
     return like

pmf是 效率的 题 得到的原始得分的分 ,like是 察到分 的概率。

图12-4显示了爱丽 和 效率的后 分 。 期的那 ,爱丽 的分 位 更 ,靠近右 ,


有一 重 部分。
图12-4
 爱丽 和 题效率的后 分

用TopLevel,我们 较 A(爱丽 效率更 的 )和 B( 效率更 的 )。


然 为3.4, 我们 型(3.8)得到的小 。 此,这个 型 , 据的证据支 A, 弱
的 。

我们的先 是A和B 可能,那么参 这个证据,我们会给 A
77%的后 概率, 外有23%的


可能, 的效率更 。

12.8
 预测分布
到目 为 我们 做的分 了爱丽 和 的效率, 由 效率是无法直接 察到的 以 以
证结 。

为了让 型有 的能 ,可以用 来 一个 的问题:“ 爱丽 和 进 一 SAT


学 试,爱丽 得分 的可能 是多少?”

我们 通 个步 这个问题:
 

用效率的后 分 来生成 个 试接受 原始得分的后 分 。


较这 个 分 , 爱丽 得到更 分 的概率。
我们 有了大部分 要的 。为了 分 ,可以 用MakeRawScore-Dist:
exam = Exam()
a_sat = Sat(exam, 780) 
b_sat = Sat(exam, 740) 

a_pred = exam.MakeRawScoreDist(a_sat) 
b_pred = exam.MakeRawScoreDist(b_sat)

接着,我们可以得到在 中爱丽 分 , 分 , 他们分 的可能 :


    a_like = thinkbayes.PmfProbGreater(a_pred b_pred) 

    b_like = thinkbayes.PmfProbLess(a_pred b_pred) 

    c_like = thinkbayes.PmfProbEqual(a_pred b_pred)

爱丽 在 中得分更 的概率是63%,这 着 更 分的概率是37%。

请 ,我们对爱丽 的效率更有 心, 下一 的 心。爱丽 的效率较 的后 赔率是


3:1, 在下一个 试中,爱丽 更好的赔率只有2:1。

12.9
 讨
我们以问题“爱丽 准 更充分的证据有多强”为 章的开始,这个问题 上 起来像我们想
试 个 :要么爱丽 ,要么 准 得更好。

为了 这 的 然度,我们必须 决一个 问题。对 个参 试 ,我们必须找到


p_correct efficacy的后 分 。

这 的 称为干 参 , 为我们 上不 心 们是什么, 为了 心的问题必须 这


量。

章中我们 现可 分 结 的 法是绘 这 参 的 分 。thinkbayes.MakeJoint接收 个


Pmfs对象, 们的 合分 ,并 个可能的 和概率对的概率密度 。
def MakeJoint(pmf1, pmf2): 
    joint = Joint()
    for v1, p1 in pmf1.Items():
        for v2, p2 in pmf2.Items():
            joint.Set((v1, v2), p1 * p2) 
    return joint

此 个分 是独 的。

图12-5显示了 p_correct (爱丽 和 )的 合后 分 。 中的对 线 示爱丽 和 的


p_correct 的情况。在这条线的右 ,说 爱丽 准 得更好; ,说 准 得更好。
图12-5
 爱丽 和 p_correct的 合后 分

在TopLevel.Update中, A和B的 然 时,我们 了这条线 侧的概率 量。对 在


的 元格,我们 A和B 的总 量,并 到A和B中。

我们 章中 用的过 ——为了 个互 的 然度 干扰参 ——是一 常 的 决类


问题的贝 法。

第13 
 真
在 章中,我描 了一个肾 患 问题的 决 案。我 为这个问题对 患 和进 医 的医
生来说都是重要和有 的。

我 为 很有 , 为这虽然是一个贝 问题, 是 用贝 的 式却是 含的。我 出了 法


和 ,在 章结 ,我 贝 的部分。

你想了 更多的 术细 ,可以在http://arxiv.org/abs/1203.6890 读我有 这项工 的 。

13.1
 的
我是在线统 http://reddit.com/r/statistics的忠 用户,也偶 内 。2011年11月,我在那儿
读到了以下消息:

“我现在 Ⅳ期肾癌,想 癌 是 是在我 部 以 就形成的…… 伍和 的日


期是 可以 有
50/50
的可能我是这么得 的?是 有可能 我在 伍日期时患 的概率是多少?
时,我的 为15.5×15 米,Ⅱ 。”

我 了消息的 ,并 得了更多的 息,我了 到, “可能 非不是”①是在部 服 期


形成的, 伍军人可以得到 偿是不 的(除其他 外)。

为肾 生 缓 ,通常也没有什么 发的 状,可以有时并不进 疗。 医生还是会 察


,并 较 一 人未 的 在不 时 的生 速率。有 篇 报导了这 生 率。

我 Zhang②的 中找到了一 据,并 了 看能 得到原始 据。不过他们以患


的原则 了。不过我还是能 绘 出他们的报告 据图形, 则进 量来 取出我 要的 据。

他们以倍 时 率 (RDT)的形式报告了 率, 以倍 体/ 年的形式。 此,RDT=1


示 年 双倍体积;RDT=2 示 年四倍;RDT=-1, 示一 。图13-1显示了53例患 RDT的
分 。
图13-1
 RDT( 年倍 体积)的CDF

是 上的 据点;虚线是我就 据拟合 成的 型。 线条的 部分和指 分 拟合得很


好, 以我用了 个 合的指 。

13.2
 一个简 模型
在尝试更有挑 的东西 , 用 型一般是不 的。对 手 的一 问题 型有时就
了, 不是,你还可以用 型来 证更 杂的 型。

我的 型是: 为 的生 有 的倍 时 , 是三维的, 一维 度 量
翻倍,体积就是 倍(2×2×2=8)。

我 案例的合 到,他 军 伍到 断日是3291天(约9年)。 以,首先要 的就是“


以中位速率 ,那么 在 伍日时有多大?”

体积倍 时 的中位 , Zhang的报告中看约为811天。 一个三维 体, 度 的倍 时 为


的3倍。
# time between discharge and diagnosis, in days 
interval = 3291.0

# doubling time in linear measure is doubling time in volume * 3
dt = 811.0 * 3

# number of doublings since discharge
doublings = interval / dt

# how big was the tumor at time of discharge (diameter in cm) 
d1 = 15.5
d0 = d1 / 2.0 ** doublings

你可以 http://thinkbayes.com/kidney.py下载 章 。更多 息,请参 的“ 指南”。

结 d0约6 米。 此, 这个 是在 伍日期后形成的, 必须以大幅超过平均速度的速度


。 此,我可以断 是“可能 非不是”在 伍 形成的。

此外,我 的 率能暗示 是 是 伍 形成的。 其 始大小为0.1 米,我们可以


出达到15.5 米最 寸的倍 量:
# assume an initial linear measure of 0.1 cm
d0 = 0.1
d1 = 15.5

# how many doublings would it take to get from d0 to d1
doublings = log2(d1 / d0) 

# what linear doubling time does that imply? 
dt = interval / doublings

# compute the volumetric doubling time and RDT
vdt = dt / 3
rdt = 365 / vdt

dt是线 的倍 时 , 以vdt是体积的倍 时 ,rdt是 倍 时 。

倍 量以线 度 量是7.3,这 着RDT是2.4。在Zhang 人的 据中,只有20%的 在 察期


中 这么快。

以, 一 ,我得出的结 是“较有可能” 形成 伍 。

这 都 以 的那个问题,我 合 给 伍军人福利 VBA写了一封 , 我的结


,后来我还 结 告诉了我的一个 科医生朋 。他对Zhang 人 察到的 速度和生 年龄
感到惊 。他指出对 研究人 和医生,这一结 都会 起 。

是为了让 型更有用,我想要找到一个更普 的 年龄和大小 的 型。

13.3
 更 遍的模型
在 断时的大小, 道 在 一个给 时 形成的概率, 年龄(生 时 )
的分 是最有用的。

为了得出结 ,我 了 真 生 的 ,得到在 生 年龄的条件时, 大小的分 。然


后我们可以用贝 法得到 寸条件时的年龄分 。

真以一个小 开始,并以下 这 步 :

1. RDT的分 中选取一个 率;

2.在 个 的结 的 寸;

3.记 在 个时 隔里 的 寸;
4.重 ,直到 超过最大的 应 寸。

对 始 寸,我选取了0.3 米, 为 这小的 不太可能有 入 以 快速 的 液


应( http://en.wikipedia.org/wiki/Carcinoma_in_situ)。

我选择了245天(约8个月)的 , 为这是 据 中 量对象的平均时 。

最大 寸我选择了20 米,在 据 中, 察 的 寸 围是1.0~12.0 米, 以可以 断这超出


了 围的 端, 不多, 不太可能对结 有显著 。

真基 一个较大的 : 率 为在 个 内是独 互不 的, 此 不依 年龄、大


小, 一个 的生 速率。

在 135 的“ ”中,我 顾 了这 并 了更 详细的 型。不过我们首先来看


一 例子。

图13-2显示了 真的 寸 (图形),以年龄 为变量。10 米 的虚线显示了 在 寸


的年龄 围: 最快的 为8年;最 的超过35年。

图13-2
 的 真时 和大小
我用线 度展示出结 , 上是依据体积进 的。 ,为了 一个转 到 一个,我以
给 的直径来 示球体的体积。

13.4
 实现
下 是这一 真的 心 :
def MakeSequence(rdt_seq, v0=0.01, interval=0.67, vmax=Volume(20.0)): 
    seq = v0, 
    age = 0

    for rdt in rdt_seq: 
        age += interval
        final, seq = ExtendSequence(age, seq, rdt, interval) 
        if final > vmax: 
           break

    return seq

rdt_seq是 率
CDF
产生 的 器。v0是以毫 (mL) 示的 始体积。interval是以年


的时 隔。vmax是对应20 米 度的最 体积。

Volume 度 量的 米(cm) 转 为毫 (mL)体积,基 是一个 球体这个 条


件:
def Volume(diameter, factor=4*math.pi/3): 
    return factor * (diameter/2.0)**3

ExtendSequence在时 隔结束时 的体积。


def ExtendSequence(age, seq, rdt, interval): 
    initial = seq[-1] 
    doublings = rdt * interval
    final = initial * 2**doublings
    new_seq = seq + (final,) 
    cache.Add(age, new_seq, rdt) 

    return final, new_seq

age 是 在 隔 结束时的生 年龄。 seq 是一个 含 体积的元 。 rdt 是 隔期 的


率, 年倍 。interval是以年 的时 步 。

final是 在时 隔结束时的体积, new_seq是一个新的含有seq 上新 出的体积final


的元 。

Cache.Add在 个时 隔的末 记 个 的年龄和 寸,下 会进 。

13.5
 存联 分布
以下是cache的功能。
class Cache(object): 

    def __init__(self): 
        self.joint = thinkbayes.Joint()

joint是一个记 个年龄- 寸对 率的 合Pmf对象, 以 近 年龄和大小的 合分 。


在 个 真 隔结束时,ExtendSequence调用Add:
# class Cache

    def Add(self, age, seq): 
        final = seq[-1] 
        cm = Diameter(final) 
        bucket = round(CmToBucket(cm)) 
        self.joint.Incr((age, bucket))

,age为 的年龄,seq是 目 体积的 。

新 据到 合分 ,我们用Diameter 体积转 到直径,以 米为 位:


def Diameter(volume, factor=3/math.pi/4, exp=1/3.0): 
    return 2 * (factor * volume) ** exp

CmToBucket 米转 到一个 散的量bucket:


def CmToBucket(x, factor=10): 
    return factor * math.log(x)

buckets 隔分 对 度。利用 factor=
10得出一个合 的buckets 量;例 ,1 米 射到


bucket
0,10 米 射到bucket
23③。

真后,我们就可以绘 合分 的 图,其中 个 元格 在给 的大小—年龄对 察到


的 的 目。

图13-3显示了1000 真后的 合分 。
图13-3
 大小和年龄的 合分

13.6
 分布
通过 合分 取垂直切 ,我们可以得到对 给 年龄的 寸大小分 。通过做一 平切
,我们可以得到给 寸的年龄分 。

下 是对 一个给 的大小读取 合分 ,并创 条件分 的 。


# class Cache

    def ConditionalCdf(self, bucket): 
        pmf = self.joint.Conditional(0, 1, bucket) 
        cdf = pmf.MakeCdf()
        return cdf
bucket是对应 大小的整 。Joint.Conditional 给 bucket 下年龄的PMF。其结 是给
bucket下年龄的CDF。

图13-4显示了这 个在不 大小下的CDF。总结这 分 ,我们可以 出不 大小 下的 分


位 。

图13-4
 给 大小条件下, 生 年龄的分

percentiles = [95, 75, 50, 25, 5] 

for bucket in cache.GetBuckets():
    cdf = ConditionalCdf(bucket)      
    ps = [cdf.Percentile(p) for p in percentiles]

图13-5显示了 个大小 的这 分位 。 据点 的 合分 中 得到。在 型中大小


和时 是 散的,这产生了 误差, 以我也展示了就 个 分位 的最小 拟合 线。
图13-5
 的年龄 为大小的 的 分位

13.7
 序列
到目 为 ,得到的结 都是基 多项 决 的;让我们 顾一下这 ,看看 是误差最有
可能的来 。
 

要转 线 量到体积,我们 近 球形。这个 对 米的 很合 ,对非常大的


却不 。
在 真过 中, 率的分 是基 一个我们选择的和Zhang 报导 据拟合的 续 型, 据基
53 患 。 拟合只是近 的,更重要的是,大一 的 可能产生不 的分 。
生 型没有 型 。这一 是为了 Zhang 人的结 一 :“不 大小、子类
型和 肾 的 率构成了一个广泛的 围并 上重 了在一起了。” 是在大的 量
下, 们 的差异可能会变得更 显。
生 速率的分 不依 的大小。对 非常小和非常大的 ,这一 是不符合 的,
是由 液 应 的。

Zhang 人 的 大小为1-12 米, 他们没有发现大小和 速度 的统 显著 。


以 上 在, 至少在这个 寸 围内很可能只是弱的(译 : 示没有 )。
 

在 真中, 个 隔期 的 速率是独 隔的 率的。 上这是 是 非的, 速


过了的 更可能(在下一个 隔) 续快速 。 说, 速率可能 后 。

其中, 一个和最后一个 最有问题。首先调查下 后 , 过 来 球 。

为了 真有 的 生 ,我写了一个generator④,能 一个给 的Cdf产生一个 。下


是 法的工 原 。

1. 分 生成 。这很 , 为我们能以 一 为条件 下一 的分 。

2.利用 CDF, 个 转 为其 积概率。

3.通过给 Cdf, 积概率转 为 应 。

下:
def CorrelatedGenerator(cdf, rho): 
    x = random.gauss(0, 1) 
    yield Transform(x) 

    sigma = math.sqrt(1 - rho**2);    
    while True: 
        x = random.gauss(x * rho, sigma) 
        yield Transform(x)

cdf是 的Cdf
;
rho是 的 子,x是 ;Transform 们转 成 的分 。

x的
一个 是均 为0, 准 差为1
的 。对 后续 ,平均 和 准 差依 先 的 。
给 上一个x,下一个 的平均 为x * rho, 差为1
-
rho**
2
。

Transform 个 x 射到一个给 Cdf的 y。

def Transform(x): 
    p = thinkbayes.GaussianCdf(x) 
    y = cdf.Value(p) 
    return y

GaussianCdf 在x 上 准 分 的CDF, 积概率。Cdf.Value 积概率 射到cdf的对应


根据cdf的形状, 息可能会在转 中遗 , 以 可能 rho更 。例 , 我 rho=
0.4


的 率产生10000个 , 为0.37。 是,由 我们只是在对 的 量进 猜 ,这就
接近 了。

请记住,MakeSequence 要以一个 器 为参 。 接口允许以不 的生成器 为参 :


iterator = UncorrelatedGenerator(cdf) 
seq1 = MakeSequence(iterator) 

iterator = CorrelatedGenerator(cdf, rho) 
seq2 = MakeSequence(iterator)

在这个例子中,seq1和seq2 一分 取得, seq1中的 是不 的, seq2的 以近 rho的



现在,我们可以看到 对结 产生的效 。下 的 显示了一个6 米的 的年龄 分位
,分 用了不 的生成器和有 ρ=0.4的生成器。

 年 的 分  
 序列     ( 米) 
 5   25   50   75   95 
 0.0   6.0   10.7   15.4   19.5   23.5   30.2 
 0.4   6.0   9.4   15.4   20.8   26.2   36.9 

得 最快的 更快,最 的速度更 , 以年龄的 围就越宽。不 的是 对 分


位 是 中的, 对 95 分位就是6年多。为了 这 分位 ,我们 要一个更好的
后 的 。

然 ,这 式就 以 我们开始的问题:给 一个 度 寸是15.5 米的 , 形成了8年以


上的概率是多少?

下 是 :
# class Cache

    def ProbOlder(self, cm, age): 
        bucket = CmToBucket(cm) 
        cdf = self.ConditionalCdf(bucket) 
        p = cdf.Prob(age) 
        return 1-p

cm 是 的大小;age是以年 的阈 。ProbOlder 转 大小到bucket ,得到给 bucket下的年龄的


Cdf
,并 这个年龄超过给 的概率。

生 没有 后 的条件下,一个15.5 米 的年龄是8岁以上的概率是0.999
, 切无
了。 为0.4的 下, 一个更快生 的 ,概率 然是0.995。 为0.8,概率还是0.978。

误差的 一个可能来 就是 近 球形。对 一个 度 寸为15.5
×15 米的 ,这


可能不合 。 合 ,就好像是说, 这个 寸的 是 对平 的,应 和 径6 米球体的
有 的体积。 到更小的体积和 0.8,年龄大 8的可能 然是95%。

此, 到 误差,这么大的 形成不到8年也是不可能的。

13.8
 讨
好了,我们一整章都没有 用贝 封 了贝 更新的Suite类。怎么 事?

贝 的一 法是 其 为反向得到条件概率的一个 法。给 p(B|A),只要我们 道


p(A)和p(B),就可以 p(A|B)。 然只有在 p(B|A) p(A|B) 的情况下, 法 是
有用的(由 原 )。

在这个例子中,通过 真,我们可以 年龄条件时 寸的分 , p( 寸|年龄)。


寸时年龄的分 , p(年龄| 寸)是很 得到的。 此,这 是一个 好的应用贝 的
会。

我没有这么做的原 是 效率。要 对 给 寸的p( 寸|年龄),你必须 量的


真。最后,你要在很大 围的 寸 来 p( 寸|年龄)。事 上,你最 整个 寸和年龄
的 合分 p( 寸,年龄)。
一 得到 合分 ,就的 不 要贝 了,你可以通过切 合分 取p(年龄|
寸),这 在ConditionalCdf中 过。

以,我们是绕过了贝 , 我们 他 在。

①此 原 是more
likely
than
not,也可以 译为可能, 案例的 殊 ,应 和法 严谨 有 ,


以直译。

②Zhang .利用一 积CT 量法 肾 的生 速率分 [J]. 射学2009,1(250 )137-


144。

③译 :bucket直译不恰 , 原 。

④ 你对Python
generator不 悉,请参 http://wiki.python.org/moin/Generators。



第14 
 层次 模型

14.1
 器
我是 姆· 贝 -里基 那儿 道下 这个问题的,他是“最大熵”博客http://maximum-entropy-
blog.blogspot.com的 。 他是 的《概率 :科学的 》的 E.T. 恩 那儿 道这个问题
的:

一个 射 ,以平均 r个 子的速度向一个 器发射 子, 器只能记 击


中 的 子的一部分,一个分 f, f为10% 器在1 的时 内记 了15个 子,那么 子
击中 器的 量n的后 分 是什么? 子平均发射速率r的后 分 是什么?

要 决这 一个问题,我们要 统以这 参 为开始,以 到的 据为结束 的 链:

1. 射 以平均速率r发射 子。

2.在 给 的1 内, 射 向 器发射了n个 子。

3.n个 子中,只有其中k个 记 下来。

原子衰变的概率在 时 都是 的, 以 射 衰变可以很好 为一个 松过 。 r,则n


的分 是参 为r的 松分 。

并 我们 到 个 子的概率是独 的,k的分 是参 为n和f的 项分 。

给 统的参 ,可以 得 据的分 。 以我们可以用 的 (直接 路)来 决。

现在,我们希望用 一个 法: 据, 得参 的分 。这就是 的 。 能 决
向问题,你就可以 用贝 法来 决 向问题。

14.2
 简 的开
让我们 问题的一个 的 —— r ——开始。给 f的 , 以要做的就是 n。

我 了一个 为Detector的Suite对象,对 器 并 n。
class Detector(thinkbayes.Suite):

     def __init__(self, r, f, high=500, step=1):
         pmf = thinkbayes.MakePoissonPmf(r, high, step=step)
         thinkbayes.Suite.__init__(self, pmf, name=r)
         self.r = r
         self.f = f

平均发射速率为 r个 子,则n的分 是参 为r的 松分 。high和step 为n的上界和


的步 大小。

现在我们 要一个 然 :
# class Detector

     def Likelihood(self, data, hypo):
         k = data
         n = hypo
         p = self.f

         return thinkbayes.EvalBinomialPmf(k, n, p)

data是 到的 子 量,hypo是发射出的 子的 量。

上有n个 子,并 到 们中的 一个的概率为f,则 到k个 子的概率由 项分


给出。

这就是 器对象了。我们可以试着 出r 的 围:
     f = 0.1
     k = 15

     for r in [100, 250, 400]:
         suite = Detector(r, f, step=1)
         suite.Update(k)
         print suite.MaximumLikelihood()

图14-1显示了n对 个给 r 的后 分 。

图14-1
 3个不 r 下n的后 分 。

14.3
 分层模型
在上一 中,我们 r为 的。现在,让我们 松这一 。我 了 一个Suite对象,称为
Emitter, 对发射器 并 r的 围:
class Emitter(thinkbayes.Suite):
     def __init__(self, rs, f=0.1):
         detectors = [Detector(r, f) for r in rs]
         thinkbayes.Suite.__init__(self, detectors)

rs是r 的 。detectors是 器对象的 , 一个对应 一个r 。对象中就是 器的


个 , 以Emitter是一个 Suite对象;也就是说, 是以其他Suite对象为 的Suite对象。

要更新Emitter,我们必须 个r的 下的 据的 然度。 r的 是由一个 含了n 围


的 器对象 示的。

要 对 给 的 器下 据的 然度,我们通过 环n的 有 ,然后 k的 总概 率 。


SuiteLikelihood 现这个功能:

# class Detector

     def SuiteLikelihood(self, data):
         total = 0
         for hypo, prob in self.Items():
             like = self.Likelihood(data, hypo)
             total += prob * like
         return total

现在我们可以写出发射器的 然 :
# class Detector

     def Likelihood(self, data, hypo):
         detector = hypo
         like = detector.SuiteLikelihood(data)
         return like

一个hypo是一个 器, 以我们可以调用SuiteLikelihood得到 下 据的 然度。

更新了发射器后,我们也必须更新 个探 器。
# class Detector

    def Update(self, data):
        thinkbayes.Suite.Update(self, data)

        for detector in self.Values():
            detector.Update()

像这 有多 Suite对象的 型 称为分层模型。

14.4
 一个小优
你也许对SuiteLikelihood有印象;我们在 110 “来一个 平的对 ”中 过 。 时我指出我们并
不真的 要 , 为由SuiteLikelihood 的总概率是由Update 并 的归一 常 。

以,不用先更新发射器, 更新探 器,我们其 可以 时 成这 步, 用 Detector.Update


得到的结 为发射器的 然度。

下 是Emitter.Likelihood的 :
# class Emitter

    def Likelihood(self, data, hypo):
        return hypo.Update(data)
以这个 的Likelihood,我们就可以 用Update的默 。 此 更少, 为 不用
归一 常量 , 以 得更快。

14.5
 抽 后验
更新了发射器后,我们可以通过 环探 器和其概率得到r的后 分 :
# class Emitter

    def DistOfR(self):
        items = [(detector.r, prob) for detector, prob in self.Items()]
        return thinkbayes.MakePmfFromItems(items)

items为r的 其概率的 。其结 是r的Pmf。

为了得到n的后 分 ,我们必须 出探 器的 合分 。我们可以 用thinkbayes.MakeMixture,


接收 射 个分 和其概率的元Pmf。这 上也就是发射器:
# class Emitter

    def DistOfN(self):
        return thinkbayes.MakeMixture(self)

图14-2显示了结 。毫不 ,n最可能的 是150。 f和n,则 为k
=
fn, 以给 f和k,n的


期望 为k/f。也就是150。

图14-2
 n和r的后 分
150个 子在1 内 发射,r的最可能的 是 150个 子。 此r的后 分 也集中在150附
近。

r的后 分 和n是 的;唯一的 是,我们对 n稍不 。一般来说,我们对 较 时 围


的发射率r更 , 对 1 内的 子发射 量n却不是那么 。

你可以 http://thinkbayes.com/jaynes.py下载 章 。更多 息,请参 的“ 指南”。

14.6
 讨
器问题 和分 型 的 。在 示例中,发射率r对 子 n有 效应,
n对 子 量k有 效应。

分 型反 了 统的结构,在 部产生 , 底部得到效 。

1.在 ,我们以r的一 开始。

2.对 一个r的 ,我们有一个n的 的 围,这取决 n的先 分 。

3. 更新 型时,我们自下 上。对 个r n的后 分 ,然后 r的后 分 。 以


息沿着 结构由上至下, 断过 自底向上。

14.7
 习
练习14-1。

这项工 也是受到 恩 《概率 》 中一个例子的 发。

你买了一个 期能降 家里附近蚊 量的捕蚊器。 你都清 这个 , 的蚊


量。 一个星期后捉到30只蚊子。 个星期后捉到20只蚊子。那么请 你的 子里蚊子 量的 分
变 。

要 这个问题,必须做出一 的决 。这里有一 下:
 

个星期有大量蚊子N在你家附近的 地生 。
一 内,N中一部分f1进入你的 子里,f1中一部分f2 入 。
在你的 法中,要 到“N 可能的变 量”的先 点,可以通过在分 型中 一个 来
对N变 的 分 。


第15 
 理多

15.1
 细
肚 生物多 2.0(BBB2)项目是一个 国 的 科学项目, 在 可以在人类肚 上找到的
细菌 类(http://bbdata.yourwildlife.org)。 项目 异想天开, 是人们越来越 人体微生物的
势的一部分,人体微生物就是那 生活在人体 体 部分的微生物的集合。

在试 研究中,BBB2研究人 收集了60 志愿 部的 ,用 用 法 取并进 16S


rDNA 段的 ,然后 其物 基 段的来 。 一个 出的 段 称为“ 记 ”①。

我们可以利用这 据来 个 问题:
 

基 察到的物 的 量,我们能 在环境中物 的总 ?


我们能 一个物 的 群 例, 一个物 占总体的分 ?
我们 收集额外的 ,能 有多少新物 可能会 发现?
要 察到的物 的 例 到一个给 的阈 , 要多少额外的“ 记 ” 段?

这 问题构成了 的 知 种 。

15.2
 子 老 和
我 这个问题的一个 开始。在这个 中,我们 物 的情况, 称 为狮子、
和熊。 我们参 生动物 护 ,看到了3只狮子、2只 和1 熊。

我们在 护 察到 动物物 的 会均 ,则 个物 的 量由多项分 决 。 狮子、


和熊的 群 率是p_lion、p_tiger和p_bear,看到3只狮子,2只 和1 熊的可能 就是
p_lion ** 3 * p_tiger ** 2 * p_bear ** 1

一 人 不 的 法是用beta分 ( 32 的“Beta分 ”)来分 描 个物 的 群 例。例


,我们看到3只狮子和3只“非狮子”; 我们 其 3个“ ”和3个“反 ”的 ,那么p_lion的后
分 就是:
    beta= thinkbayes.Beta ()
    beta.Update ((3,3))
    print beta.MaximumLikelihood ()

p_lion的最大 然 就是 察到的 例50%。 ,p_tiger和p_bear的最大 大 然 为33%和


17%。

这里有 个问题:

1.我们 含地为 个物 用了一个均 的 0到1的先 , 是 为我们 道有3个 , 以


其 这个先 是不 的。 的先 应 是平均 为1/3,并 在(其他的)物 有100%的 群 例
时 然度应 为 。
2. 个物 的分 不是独 的, 为 群 例总和为1。为了体现这 依 ,我们 要3个物 群
例的 合分 。

可以用一个狄利克雷 决这 个问题( http://en.wikipedia.org/wiki/Dirichlet_distribution)。就 我们


以beta分 来描 不均 币的分 一 ,我们可以 用狄利克雷分 来描 p_lion,p_tiger和p_bear的
合分 。

狄利克雷分 是beta分 的多维通用 。 、反 这 双 结 不 ,狄利克雷分 能


量的结 :在这个例子中,是3个物 。

有n个结 ,狄利克雷分 是由n个参 描 的,记为α1到αn。

thinkbayes.py中,有一个 了狄 的类 下
:
class Dirichlet(object):

     def __init__(self, n):
         self.n = n
         self.params = numpy.ones(n, dtype=numpy.int)

n为维 ;最 的参 都是1,我用numpy 储参 ,这 我可以利用 操 的优势。

给 一个狄利克雷分 , 个 群 例的 缘分 是一个beta分 ,我们可以 下:


    def MarginalBeta(self, i):
        alpha0 = self.params.sum()
        alpha = self.params[i]
        return Beta(alpha, alpha0-alpha)

i是我们想要的 缘分 的指 。alpha0是参 的总和;alpha是对 给 物 的参 。

在 示例中, 个物 的 缘分 ,
为Beta(1 2)。我们可以 平均 下:
    dirichlet = thinkbayes.Dirichlet(3)
    for i in range(3):
        beta = dirichlet.MarginalBeta(i)
        print beta.Mean()

期的那 , 个物 群 例的 均 是1/3。

要更新狄利克雷分 ,我们 这一 察结 到参 :
    def Update(self, data):
        m = len(data)
        self.params[:m] += data

这里data 是和 params 顺 一 的一个 , 以在这个例子中, 应 是狮子、 和熊的


量。

data可以 params ;在这 情况下, 着有一 物 没有 察到。

下 是以 察到的 据更新dirichlet并 后 缘分 的 。
    data = [3, 2, 1]
    dirichlet.Update(data)

    for i in range(3):
        beta = dirichlet.MarginalBeta(i)
        pmf = beta.MakePmf()
        print i, pmf.Mean()
图15-1显示了结 。平均 群 例的后 是44%、33%和22%。

图15-1
 三个物 群 例的分

15.3
 分层 本
我们 决了这个问题的一个 : 我们 道有多少物 ,我们可以 一个的 群
例。

现在让我们 到原来的问题, 物 的总 。要 决这个问题,我会 一个元Suite对象, 是一


个 含其他Suite对象 为 的Suite对象。在这个例子里,最上 的Suite对象 含物 量的 ,底
含 群 例的 。

类 下:
class Species(thinkbayes.Suite):

     def __init__(self, ns):
         hypos = [thinkbayes.Dirichlet(n) for n in ns]
         thinkbayes.Suite.__init__(self, hypos)

__init__取为n的可能 的 ,并创 一个狄利克雷对象的 。

下 是创 Suite对象的 :
    ns = range(3, 30)
    suite = Species(ns)
ns 是 n 的可能 的 。由 看到3个物 , 以必须为至少3个。我选择了一个 合 的上
,稍后会 查得 超过这个界 的概率很 。并 至少在最 段,我们 在此 围内的 都是
可能的。

要更新一个分 型,你必须更新 有 。通常必须先更新底 向上更新, 在 例中,我们可


以先更新 :
#class Species

   def Update(self, data):
       thinkbayes.Suite.Update(self, data)
       for hypo in self.Values():
           hypo.Update(data)

Species.Update调用父类中的Update,然后 历子 并更新 们。

现在,我们 要一个 然 :
# class Species

     def Likelihood(self, data, hypo):
         dirichlet = hypo
         like = 0
         for i in range(1000):
             like += dirichlet.Likelihood(data)

         return like

data是 察到的 ;hypo是一个狄利克雷对象。Species.Likelihood调用Dirichlet.Likelihood


共1000 然后 总和。

为什么调用1000 ? 为 Dirichlet.Likelihood 上并不 据在整个狄利克雷分 上的 然


度。 反, 的分 中取得一个 然后 据在这个 群 例 集下的 然度。

下 是 例:
# class Dirichlet

    def Likelihood(self, data):
        m = len(data)
        if self.n < m:
            return 0
        x = data
        p = self.Random()
        q = p[:m]**x
        return q.prod()

data的 度是 察到的物 的 量。 看到的物 我们 在的多, 然度就是0。

则,我们 选择一 群 例p, 多项式Pmf,也就是:

pi 为 i个物 的 群 例,xi 是 察到的 量。 一项cx 是多项式 ;我 其 在在


外 , 为 依 据 的 法 子 不 是 , 以 归 一 了 (
http://en.wikipedia.org/wiki/Multinomial_distribution)。

m是 察到的物 的 量。我们只 要p的 m个元 。至 其他的部分:xi为0, 以 为1,我们可以


在结 中 。
15.4
 机抽样
有 法可以 狄利克雷分 产生 。一个是 用 缘beta分 , 在这 情况下,你必须
一 选 取 一 个 扩 展 到 余 下 的 , 得 们 和 为 1 ( 参
http://en.wikipedia.org/wiki/Dirichlet_distribution#Random_number_generation)。

一个没那么 显 速度更快的 法是 n个 (gamma)分 中选取 ,然后通过除以总和来归


一 。下 是 :
# class Dirichlet

    def Random(self):
        p = numpy.random.gamma(self.params)
        return p / p.sum()

现在,我们准 好查看结 了。下 是 取n的后 分 的 :


     def DistOfN(self):
         pmf = thinkbayes.Pmf()
         for hypo, prob in self.Items():
             pmf.Set(hypo.n, prob)
         return pmf

DistOfN通过在 中 ,并 个n的概率。

图15-2显示了结 。最可能的 是4,3到7 的 也很有可能; 后的概率就 速下降了。有29个


物 的概率 到 以 略不 ; 我们选择了一个更 的上界,也会得到 一 的结 。

图15-2
 n的后 分
请记住,这个结 基 n的先 是均 分 的。 我们 道物 在环境中 量的 景 息,我们可
以选择一个不 的先 
。

15.5
 优
必须承 ,我对 这个例子中的 法很自豪。未 物 问题并不 , 这个 法 了,只用了
少的 以 (约50 )。

唯一的问题是 。对 只有3个 察物 的例子 好, 对 肚 问题的 据就不 好了


——这类 据的 中有超过100个物 。

接下来的 了一 扩展这个 法的优 法。在 入到细 里 ,路线图 下。


 

一步是要 到, 我们以 的 据更新狄利克雷分 ,对 有的 , m个的参 都是


的。唯一的 是 的未 物 量。 此,我们并不真 要n个狄利克雷对象;我们可以在
结构上 储最上 的参 。Species2 现了这个优 。
Species2也对 有 用了 的一 。这 省了生成 的时 , 还有更重要的
个好 :通过 给 有的 的选取 , 得在 的 较更 平, 以
只 较少的 就能收 。
有了这 改动,还有一个重大的 能问题。 着 察到的物 的 , 群 例的 也变
大了, 选取到一个近 的 的 率就变小了。 以 大多 得到的 然度很小,以
对总和产生的 不多,也就没有在 产生 。

决 法是 只更新一个物 ,Species4是 用狄利克雷对象来 示子 这一 略的一个


现。

最后,在 型 Species5结合子 ,并 用numpy 以 快速度。

你对细 不感兴 ,可以 到156 的“肚 据”,在那儿查看来自肚 据的结 。

15.6
 的层次
有底 的狄利克雷分 以 的 据更新, 以对 们来说, m个参 。我们可以通过 参
合并入 Suite对象来消除这一重 过 。Species2 现了这一优 :
class Species2(object):

     def __init__(self, ns):
         self.ns = ns
         self.probs = numpy.ones(len(ns), dtype=numpy.double)
         self.params = numpy.ones(self.high, dtype=numpy.int)

ns是n 的一个 ;probs是 应概率的 。 params是狄 参 的顺 , 始 有的参 都


为1。

Species2.Update更新这一分 ( 型)的 个 。 一 是n的 个可能 的概率,下一 是


狄利克雷参 :
# class Species2

    def Update(self, data):
        like = numpy.zeros(len(self.ns), dtype=numpy.double)
        for i in range(1000):
            like += self.SampleLikelihood(data)

        self.probs *= like
        self.probs /= self.probs.sum()

        m = len(data)
        self.params[:m] += data

SampleLikelihood然度的一个 , 一个 然度 对应 n的 个可能 。Like 1000个


总的 然度。self.probs 以总 然度,然后归一 。最后 更新参 ,和Dirichlet.Update一 。

现在,让我们来看看SampleLikelihood,这里有 个可优 的地 。
 

物 的 想 n超过 察到的 目m,我们只 要多项式PMF的 m个项;其余均为1。


物 的 量很大, 据的 然度用浮点 来 示可能太小(请参 99 的“ 据下溢”)。
此, 对 然度要更 。

, 多项式的PMF是

以对 然度是

更快速 。 ,cx 对 有 是 的, 以我们可以 在一 先不管 。下 是



# class Species2

    def SampleLikelihood(self, data):
        gammas = numpy.random.gamma(self.params)
        m = len(data)
        row = gammas[:m]
        col = numpy.cumsum(gammas)

       log_likes = []
        for n in self.ns:
            ps = row / col[n-1]
            terms = data * numpy.log(ps)
            log_like = terms.sum()
            log_likes.append(log_like)

        log_likes -= numpy.max(log_likes)
        likes = numpy.exp(log_likes)

        coefs = [thinkbayes.BinomialCoef(n, m) for n in self.ns]
        likes *= coefs

        return likes

gammas是一个 分 构成的 , 的 度是n 的最大 。row是gammas 的 m 个元 ;


为这 参 依 据 , 以这 就是我们 要的 部参 了。

对 n的 个 ,我们 要 row除以gamma中 n项 的总和,cumsum 这 积 ,并 们 储


在col中。

loop 环 n的这 , 到一个对 然 的 。

在 环内部, ps 含概率的 ,以对应的 总和进 归一。 terms 含和的 项, ,


log_like 含 们的和。
环结束后,我们要 对 然度转 为线 然度, 最好是先进 转 得最大的对 然度为
0;这 的 ,线 然度就不会显得太小(请参 “ 据下溢”99 )。

最后,在 然度 ,我们必须应用一个修 ( 子), 是我们可以 察到m个物 的可能


法的 量, 时 物 的总 为n。BinomialCoefficient 这个“n选m”过 ,写为 。

常 的那 ,优 的 可读 差,也 原始 更 出 。 这就是我 开始的一


个原 ,我们可以用 进 归 试。我绘 了 个 得到的结 ,可以 们是大 的,
并 着 们都是收 的。

15.7
 另一个
我们还可以做得更多来优 这一 , 有 外一个 要首先 的问题。 着 察到的物 目的
,这个 的 法变得让人心 , 要更多的 能收 到一个好的结 。

问题是, 我们 狄利克雷分 中选择的 群 例ps并不是近 的, 察到的 据的 然


度就会接近 , 对 n的 有 就是 的。那么大多 就不能为总体可能 有用的 。
着 察到的物 的 量m变大,以 切可能 选取ps的概率就会变小, 真是 小。

的是,有一个 决 法。 你 察一 据,你可以就整个 据集更新先 分 , 分


成一 据的子集 一更新,并 这 式更新的结 都是 的。

在这个例子中, 键是 更新是 对一个物 。这 , 我们生成一 的ps时,只有其中一个


会 到 得到的 然度, 此选择一个 对象的概率要好得多。

下 是 更新一个物 的新 :
class Species4(Species):

    def Update(self, data):
        m = len(data)

        for i in range(m):
            one = numpy.zeros(i+1)
            one[i] = data[i]            
            Species.Update(self, one)

Species 承 __init__ , 以 以一个狄利克雷对象的 来 示 (和 Species2 中不


)。

Update 历 察到的物 ,创 一个 one, 含 一个物 的 ,都先 为 。然后调用


父类的Update, 然度并更新子 。

此,在这个例子里,我们做三 更新。 一个有点像“看到了三只狮子”。 个是“看到了 只


,没有看到更多的狮子”。 三个是“看到一 熊,没有看到更多狮子和 ”。

下 是 然度的新 :
# class Species4

    def Likelihood(self, data, hypo):
        dirichlet = hypo
        like = 0
        for i in range(self.iterations):
            like += dirichlet.Likelihood(data)

        # correct for the number of unseen species the new one
        # could have been
        m = len(data)
        num_unseen = dirichlet.n - m + 1
        like *= num_unseen

        return like

这和Species.Likelihood , 不 的是 子num_unseen。这 是必要的, 为 我们


首 看到 一个物 ,我们都要 到有其他的一 我们 应看到的未 物 。对 较大的n 就会有更
多我们 应看到的未 物 ,这一 了 据的 然度。

必须承 这是一个我最开始并没有搞清 的微 , 搞清 后, 接着我就能 通过 较以 的


来 证 ( )了。

15.8
 还有 作要做
一个物 的更新 决了一个问题, 也带来了 一个问题。 更新 要的时
km,其中k是 的 目,m是 察到的物 的 量。 此, 我们做m 更新,总 时
km2。

是,我们可以利用151 “ 的 结构”中 的诀 快速度:我们 狄利克雷对象,


分 结构中的 个 折 到一个 一的对象。 以下 是Species的 一个 :
class Species5(Species2):

    def Update(self, data):
        m = len(data)
        for i in range(m):
            self.UpdateOne(i+1, data[i])
            self.params[i] += data[i]

Species2 承__init__, 以 用ns和probs 示n的分 , params 示狄利克雷分 的


参 。

Update类 我们在上一 中看到的。 历 察到的物 调用UpdateOne:


# class Species5

    def UpdateOne(self, i, count):
        likes = numpy.zeros(len(self.ns), dtype=numpy.double)
        for i in range(self.iterations):
            likes += self.SampleLikelihood(i, count)

        unseen_species = [n-i+1 for n in self.ns]
        likes *= unseen_species

        self.probs *= likes
        self.probs /= self.probs.sum()

此 类 Species2.Update, 有 个变 。
 

接口是不 的。我们得到的不是整个 据集, 是 察到的物 的 i和 看到的物 量


count。
我们要在未 物 的 量上应用一个修 , Spcies4.Likelihood 示。这里的不 在 我
们以 的 法 时更新 部 然度。

最后,SampleLikelihood 下
:
# class Species5
    def SampleLikelihood(self, i, count):
        gammas = numpy.random.gamma(self.params)

        sums = numpy.cumsum(gammas)[self.ns[0]-1:]

        ps = gammas[i-1] / sums
        log_likes = numpy.log(ps) * count

        log_likes -= numpy.max(log_likes)
        likes = numpy.exp(log_likes)

        return likes

这类 Species2.SampleLikelihood;不 的是, 一 更新只 一物 , 以并不 要一个


环。

这个 的 时 量k。 m , 此更新的 时 成 km。 以我们得


到一个准 结 要的 通常也就少了。

15.9
 据
狮子、 和熊的问题讨 得 了。现在让我们 到肚 问题。为了得到 据的含 ,
B1242 题,其400个 记 产生了 下 的61个物 :
92, 53, 47, 38, 15, 14, 12, 10, 8, 7, 7, 5, 5, 
4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1

有少 个优势物 构成了整体的很大一部分, 很多其他物 只产生一个 一的 记。这


“ ”的 目 了没 察到的物 可能至少有那么 个。

狮子和 的例子中,我们 在 护 里 动物 到的可能 是 的。类 地,对 肚


问题的 据,我们 细菌 记到的可能也是 的。

在现 中, 据收集过 中 个步 都可能 入 差。有 物 子十起的可能 大 , 产


生可 的扩 子(生物遗 学 词: 合 链式反应 得的双链 苷 产物)。 以 我们 到 一
个物 的 群 例时,我们应 要 到这 误差的来 。

还要承 ,我不太严格地 用了术语“物 ”。首先,细菌物 没有得到很好的 。其 ,有的


记能 的物 ,其他的则只能 一个 。更准 地,我应 说“操 分类 位”, 写为
OTU(operational
taxonomic
unit)。

现在,让我们来 一 肚 据。我 了一个Subject类 示研究中 个 题的 息:


class Subject(object):

     def __init__(self, code):
         self.code = code
         self.species = []

个 题都有一个字符编 , “B1242”,还有( , )对的 , 的顺


。 Subject 了 个 法,可以很 地得到这 和物 的 称。你可以
http://thinkbayes.com/species.py了 细 。更多 息,请参 的“ 指南”。

Subject 了 为Process的 法来创 和更新一个Species5 的Suite对象, n 的分 和 群


例。
Suite2 了DistOfN 法, n的后 分 。
# class Suite2

    def DistN(self):
        items = zip(self.ns, self.probs)
        pmf = thinkbayes.MakePmfFromItems(items)
        return pmf

图15-3显示了 题B1242中n的分 。 好有61个物 , 没有未 物 的概率 为 。物 量最


可能的 是72,90% 在66到79 。 横坐 的 部分来看,有87个物 的可能 很小。

图15-3
 题B1242中n的分

接下来我们 个物 群 例的后 分 。Species2 了DistOfPrevalence:


# class Species2

    def DistOfPrevalence(self, index):
        metapmf = thinkbayes.Pmf()

        for n, prob in zip(self.ns, self.probs):
            beta = self.MarginalBeta(n, index)
            pmf = beta.MakePmf()
            metapmf.Set(pmf, prob)

        mix = thinkbayes.MakeMixture(metapmf)
        return metapmf, mix

index显示了我们想要 的物 。对 个n, 群 例的后 分 不 。

环 n 的可能 其概率。由 n 的 一个 得到 示 指物 缘分 的一个Beta对象。 忘了


Beta对象 含有参 alpha和beta; 们不像Pmf对象那 有 和其概率对, 们 MakePmf ,生成近
续Beta分 的 散 。

metapmf是一个在 n的条件下, 含 群 例分 的元Pmf。MakeMixture 元Pmf结合到mix , mix


结合条件分 到一个 一的 群 例分 。

图15-4显示了 个最大物 的结 。这 最常 的物 占到了400个 记 中的23%, 由


在未 物 , 此其 群 例最有可能的 为20%,90%的 是17%~23%。

图15-4
 B1242 群 例的分

15.10
 预测分布
在4个 问题中,我 了 物 的问题。通过 n和 个物 群 例的后 分 ,我们
了 个。

外 个问题是:
 

收集更多的 ,我们能不能 可能发现多少个新物 ?


要 多少额外 记 , 能 察到物 的 例到一个给 的阈 ?

要 类 这 的 问题,我们可以 用后 分 来 真可能的未来事件,并 可能看到的物


量 的分 ,以 总 占 。

这 真过 的 心是:
1. 后 分 选取n ;

2.为 一个物 选取其 群 例, 可能的未 物 , 用狄利克雷分 ;

3.生成未来 的 ;

4. 新物 的 量,num_new, 为额外 k的 ;

5.重 的步 , num_new和k的 合分 。

下 的 RunSimulation 了一个 真:
# class Subject

    def RunSimulation(self, num_reads):
         m, seen = self.GetSeenSpecies()
         n, observations = self.GenerateObservations(num_reads)

         curve = []
         for k, obs in enumerate(observations):
             seen.add(obs)

             num_new = len(seen) - m
             curve.append((k+1, num_new))

         return curve

num_reads 是要 真的额外的 。 m 是可 物 的 目, seen 是 个物 唯一 称的字符 集


合。n是一个 后 分 选取的 ,observations是物 字的一个 。

过一 环,我们在seen中 入得到的新的 察结 ,并记 和目 新物 的 量。

RunSimulation的结 是一个 曲 , 示为 和新物 目对的一个 。

查结 ,我们来看看GetSeenSpecies和GenerateObservations。
#class Subject

    def GetSeenSpecies(self):
        names = self.GetNames()
        m = len(names)
        seen = set(SpeciesGenerator(names, m))
        return m, seen

GetNames在 据 件中的 物 称的 , 对 许多 题,这 称不是唯一的, 以我通过


SpeciesGenerator用 来扩展 个 称:
def SpeciesGenerator(names, num):
    i = 0
    for name in names:
        yield '%s-%d' % (name, i)
        i += 1

    while i < num:
        yield 'unseen-%d' % i
        i += 1

一个命 Corynebacterium,SpeciesGenerator 产生“Corynebacterium-1”这 的 字。 称


耗 时, 产生 unseen-62这 的命 。

GenerateObservations 下:
# class Subject

    def GenerateObservations(self, num_reads):
        n, prevalences = self.suite.SamplePosterior()

        names = self.GetNames()
        name_iter = SpeciesGenerator(names, n)

        d = dict(zip(name_iter, prevalences))
        cdf = thinkbayes.MakeCdfFromDict(d)
        observations = cdf.Sample(num_reads)
        return n, observations

的,num_reads是要生成的额外 。n和prevalences是后 分 的 。

cdf是一个 射物 到 积概率的Cdf对象, 未 物 , 用Cdf 产生物 称的 过


变得 效。

最后,Species2.SamplePosterior 下:
     def SamplePosterior(self):
         pmf = self.DistOfN()
         n = pmf.Random()
         prevalences = self.SamplePrevalence(n)
         return n, prevalances

SamplePrevalences生成 群 例在条件为n时的 :
# class Species2

    def SamplePrevalences(self, n):
        params = self.params[:n]
        gammas = numpy.random.gamma(params)
        gammas /= gammas.sum()
        return gammas

我们会看到这个 法 狄利克雷分 产生 ( 149 “ 抽 ” 的)。

图15-5显示了B1242 题的100个 真的稀疏 线。 线显得“ 动”是 为我为 条 线 了一个


量, 得 们不会重 在一起。通过 察,我们可以 出400个额外的 记 后,我们很可能
会发现2~6个新的物 。
图15-5
 B1242 题的 真稀疏 线

15.11
 联 后验
我们可以利用这 真来 num_new和k的 合分 ,由此,我们还可以得到num_new在k为 条
件下的分 。
def MakeJointPredictive(curves):
    joint = thinkbayes.Joint()
    for curve in curves:
        for k, num_new in curve:
            joint.Incr((k, num_new))
    joint.Normalize()
    return joint

MakeJointPredictive创 一个Joint对象, 是一个以元 为 的Pmf对象。

curves是一个RunSimulation创 的稀疏 线的 。 条 线 含k和num_new对的 。

由此产生的 合分 是 个 到其发生概率的一个 射 。给 合分 ,我们可以通过


Joint.Conditional得到num_new以k为条件下的分 ( “条件分 ” 90 )。

Subject.MakeConditionals接收一个ks的 ,并 num_new对 个k的条件分 。其结 是一个Cdf


对象构成的 。
def MakeConditionals(curves, ks):
    joint = MakeJointPredictive(curves)

    cdfs = []
    for k in ks:
        pmf = joint.Conditional(1, 0, k)
        pmf.name = 'k=%d' % k
        cdf = pmf.MakeCdf()
        cdfs.append(cdf)

    return cdfs

图15-6显示了结 。100个额外的 记 后, 的新物 的 量中 为2;90% 为0到5。


800个 记 后,我们有望看到3到12个新的物 。

图15-6
 在不 量的额外 记 条件下,新发现物 量的分

15.12

我们要 最后一个问题:“ 要 多少额外的 记 , 能 察到物 例 到一个给
的阈 ”?

要 这个问题,我们 要RunSimulation的一个能 物 的分 例的 , 不是新物


量的 。
# class Subject

    def RunSimulation(self, num_reads):
        m, seen = self.GetSeenSpecies()
        n, observations = self.GenerateObservations(num_reads)

        curve = []
        for k, obs in enumerate(observations):
            seen.add(obs)

            frac_seen = len(seen) / float(n)
            curve.append((k+1, frac_seen))

        return curve
接下来, 环 一条 线并创 一个字 d, 射额外 量k到一个fracs ,也就是在取得k个
后得到的 率 的 。
     def MakeFracCdfs(self, curves):
         d = {}
         for curve in curves:
             for k, frac in curve:
                 d.setdefault(k, []).append(frac)

         cdfs = {}
         for k, fracs in d.iteritems():
             cdf = thinkbayes.MakeCdfFromList(fracs)
             cdfs[k] = cdf

         return cdfs

这时,我们对k的 一个 创 了fracs的Cdf对象,这个Cdf 示了k个 后 率的分 。

CDF告诉了你 入给 阈 内的概率, 互 CDF告诉了你超过阈 围的概率,图15-7显示了不


k 围下的互 CDF。

图15-7
 额外 记 围的互 CDF

要 图,沿着x 选取一个 要的 率 围,例 90%,接着 图上就可以发现 k 记


后,要达到90% 率的概率。例 ,200 记,有约40%的 会得到90%的 率, 1000
记,就有90%的 会得到90%的 率。

此,我们 了未 物 问题的 部四个问题。要以 据 证 章中 到的 法,必须涉 更


多细 , 是这章 太 , 以这里我就不 续讨 了。
你 可 以 入 了 一 下 这 类 问 题 , 以 我 找 到 这 问 题 的 , 参
http://allendowney.blogspot.com/2013/05/belly-button-biodiversity-end-game.html。

你可以 http://thinkbayes.com/species.py.下载 章的 ,更多 息请参 的“ 指南”。

15.13
 讨
未 物 问题是一个活跃的研究领域,我 章中的 法为此 了一 新 。在不到200 的篇
幅里,我们 概率 基础扩展到了研究的 沿,这 我感到 兴。

中,我的目的是 达出3个 的 念。
 

贝 斯 贝 分 的 点是 用概率分 来 示尚不 的 点,通过 据来修 这 分


, 用得到的结 进 和 决 息。
方 的 是 用 法 不是 学 法 贝 分 会更 ,通过可以 合
可以重 用的 架来应用贝 法也更 。
模型:大多 真 问题都和 决 以 真 和 杂 的 有 。 先 道 要
应 纳入 型, 要 可以 抽象到 型 外通常是不可能的。最好的 法就是 , 的
型开始 杂度, 用 一个 型来交 证其他的 型。

这 念 用 强大, 的例子到最新的研究 题, 们 用 科学研究和工 的 一个领域。

你领会到了,你应 为用这 工 来 决工 中的新问题做好了准 ,希望你发现 的用


,要记得 你的收 告诉我。

①译 :参 生物学 ,原 的“read”根据上下 翻译为 记 记。



作 简
• 尼是欧 工 学 科学 的 。他 在 利学 、科 学 和 大学伯克
利分 。

他拥有U.C.伯克利的 科学博 学位和 省 工学 的硕 学 学位。




许 ,新 统架构 , 术 障部总监, 业 湖南大学,拥有15年互 工 。

于 面
《贝 维》一 封 的动物是红鲻鱼(也称为 带羊鱼)。这 可以在地中海、北大西洋东海域
和黑海发现的须鲷科鱼, 其 一 鳍后独 的条纹为人 。红鲻鱼是地中海地 人们青 的美 ,和
的须鲷科鱼——羊鱼一 ,只是羊鱼没有 一 鳍后的条纹。然 红鲻鱼要更 ,据说其 道 尝
起来类 生 。 说古 人在 中 红鲻鱼,宠爱并 练 们一 到 就 。 便是人工
的红鲻鱼一般也不到 重,其 格有时和银器一 。

非 外环境下,红鲻鱼 浅底 ,其上下唇 有独 的 称为触须的 根 须,触须用来探


海底的食物。 为 较浅的沙滩和岩 底部, 的触须 其 的近亲羊鱼 没有那么灵敏。

封 图 来自迈 •克 词 。


的翻译其 来自和编 开过的一个玩 ,我 时戏说这 的 Think
Bayes不妨译成《纪念贝
先生》, 上托 ·贝 先生也的 是一个 大的 得我们纪念的人,科学的历 是由
这 一 大的人们 动的。贝 发展并 出了我们现在 悉的贝 , 后人们也利用这一工
发展出了 的“贝 法”。读 这 ,我 读 对此会有 刻的 。

外就是 的 艾伦· 。他不 是一位 学科 , 时也是一位优秀的 家。在翻译


,我 读过他的Think
Complexity
和Think
Stats,在 的翻译过 中,你还可以看到在github上
他 在写 一 操 统的 , Think
OS。

显然,Think
Bayes是艾伦目 写得最好的一 ,原 在 在 中不 用编写Python 的 式消除


了贝 法的学习门 , 在 章的 问题中,艾伦还 默 地 会了读 怎 为 体问题创
学 型, 住问题中的 要矛盾( 型中的 键参 ), 一步一步地优 证 型的有效
。在这个过 中,你还能学习到统 分 中那 体概念的 含 和用 , 缘分 、
合分 、贝 型。

艾伦· 在github上托管了 有的Python , 读 的过 中,在自己的 器上 例


子中的 对是一件让人 的事情。

在写 中还带上了大量的概率图形, 助图 可以帮助读 更直 地 有 问题的概率形式结


我的 工 也和贝 法有 , 我们新 就 用贝 法 件,业


监控 统也可以用贝 法来进 异常指 断。至 到 统 , 也帮助我自己 清了很多有
决 的 。

总 ,这 不到200 的 对 得一读 读。

最后,我要感 人 出 社的编 给我 会翻译艾伦的 。毫无 问,艾伦是一个 得 敬的科


籍 和良 。我还要感 家人对翻译工 的支 , 是我在 静心工 的时 , 一岁的小
女儿波妞会很 地和妈妈游戏,没有干扰我。 我的女儿,我的爱人李静, 然还有无 地 我 顾
女的 亲。

译 
 许

2014年8月 颐和 北

欢迎来到 步社区

步社区的来历
异步社 (www.epubit.com.cn)是人 出 社旗下IT专业图 旗舰社 , 2015年8月上线 。

异步社 依托 人 出 社20余年的IT专业优 出 和编 团 , 统出 子
出 和自出 结合、 子 结合、 统印刷 POD 印刷结合的出 平台, 最新 术
息,为 和读 交流互动的平台。

社区里都有什么?

我们出 的图 涵 流IT 术,在编 语 、Web 术、 据科学 领域有 多 畅销图 。社


现 上线图 1000余 , 子 400多 ,部分新 现 、 子 步出 。我们还会 期发 新

下 资

社 内 附 的 , 中的案例 。

外,社 还 了大量的免 子 ,只要 成为社 用户就可以免 下载。


与作 动

很多图 的 译 入 社 , 可以 他们,咨询 术问题;可以 读不断更新的 术 章,


译 和编 畅聊好 后有 的故事;还可以参 社 的 访 目,向 的 出 访题
目。

灵活优 的购
可以 便地下 购买 图 子图 , 图 直接 人 出 社 库发货, 子
多 读格式。

对 重 新 ,社 售和新 首发服 ,用户可以 一时 买到心 的新 。

用户 户中的积分可以用 购 优 。100积分=1元,购买图 时,在 里填入可 用的积


分 , 可扣减 应 额。

   别优  

购买 子 的读 专 步社区优 。
 用 法: 成为社 用户,在下 购 时 入“57AWG”,然后点击“ 用优


”, 可 受 子 8折优 ( 优 券只可 用一 )。

电 组 购

社 独家 图 和 子 合购买 式, 格优 ,一 购买,多 读选择。

社区里还可以做什么?

可以在图 下 交勘误, 条勘误 后可以 得100积分。热心勘误的读 还有 会参


稿的审 和翻译工 。
写作

社 基 Markdown的写 环境, 写 的 可以在此一试 手,在社 里分 的 术心得


和读 体会,更可以体 自出 的 , 松 现出 的 想。

成为社 证 译 ,还可以 受异步社 的 专 色服 。

会议活动 知道

可以 握IT圈的 术会 息,更有 会免 大会门票。

加 步
描 维 都能找到我们:

异步社

微 订
微 服

官 微博

QQ群:368449889

社区网 www.epubit.com.cn

官方微信 异步社

官方微博 @人 异步社 ,@人 出 社- 息 术分社

& contact@epubit.com.cn

You might also like