Think Bayes Note 6: 欧元硬币问题

1. 问题描述

  2000 年 1 月 4 日,《卫报》上刊载了一条统计相关的声明:以边缘转动比利时一欧元硬币 250 次后,得到正面 140 次,反面 110 次。由这一结果,是否可以认为硬币是不均匀的?

2. 计算后验概率

  假设 $H_x$ 为转动硬币得到正面朝上的概率为 $x\%$,$0 \leq x \leq 100$。如果硬币是均匀的,则 $x\%$ 应接近 $50\%$。

  定义 Euro 类如下:

class Euro(Suite):
    def __init__(self, values=None):
        super().__init__(values, value_desc='x')

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

    def summary(self):
        cdf = self.make_cdf()
        print("Maximum likelihood: {}".format(self.max_likelihood()))
        print("Mean: {}".format(self.mean()))
        print("Median: {}".format(cdf.percentile(50)))
        print("Credible Interval (90%): {}".format(cdf.credible_interval(90)))
        print("P(x = 50%) = {}".format(self.prob(50)))

其中 likelihood() 方法的参数 data 为转动硬币得到的结果,用 H 表示正面,T 表示反面;参数 hypo 为得到正面的百分数(0 到 100)。如果转动硬币得到正面,则其概率为 hypo / 100.0,如果得到反面,其概率为 1 - hypo / 100.0summary() 方法用于输出一些统计量。

  下面模拟转动硬币 250 次,得到 140 次正面和 110 次反面的过程:

euro = Euro(range(0, 101))
dataset = 'H' * 140 + 'T' * 110
euro.update_set(dataset)
euro.summary()
euro.plot()

dataset 是一个由 140 个 H 和 110 个 T 组成的字符串,表示整个旋转硬币的过程;update_set() 会遍历 dataset 中的每一个字符(旋转硬币的事件),计算后验概率。

  以上代码的输出为:

Maximum likelihood: 56
Mean: 55.95238095238095
Median: 56
Credible Interval (90%): (51, 61)
P(x = 50%) = 0.020976526129544662

图像为:

  可见,后验分布的最大似然值(具有最大概率的值)是 56,等同于由观察得到的正面的百分比 \frac{140}{250} = 56\%。后验概率的 90% 可信区间为 (51, 61),不包含 50,可以认为硬币是不均匀的。

3. 三角形分布先验

  前面假设先验概率是均匀分布的,这可能并不是一个很好的假设。根据生活经验,可以认为大部分硬币都是基本均匀的,转动硬币得到正面的概率很有可能在 50% 附近,而不太可能在如 10% 或 90% 之类的极端值上。

  下面构造一个三角形的先验概率分布:

euro_tri = Euro()
for x in range(0, 51):
    euro_tri.set(x, x)
for x in range(51, 101):
    euro_tri.set(x, 100 - x)
euro_tri.normalize()
euro_tri.plot()

图像为:

此分布在 $x = 50$ 处取得最大值,向两侧线性递减。

  使用以上先验概率,模拟前述转动硬币 250 次的过程:

dataset = 'H' * 140 + 'T' * 110
euro_tri.update_set(dataset)
euro_tri.summary()
euro_tri.plot()

输出为:

Maximum likelihood: 56
Mean: 55.74349943859506
Median: 56
Credible Interval (90%): (51, 61)
P(x = 50%) = 0.02384753721469363

图像为:

  可见使用三角形先验的结果与使用均匀先验的结果非常相似。在数据充足的情况下,即使人们对先验分布具有不同的观点,也会得到趋于收敛的后验概率。

4. Beta 分布

  更进一步地,假设先验概率服从 Beta 分布。Beta 分布有 $\alpha$ 和 $\beta$ 两个参数,如果先验概率服从参数为 $\alpha$ 和 $\beta$ 的 Beta 分布,则看到 $h$ 次正面和 $t$ 次反面后的后验概率也服从参数为 $\alpha + h$ 和 $\beta + t$ 的 Beta 分布。

  定义 Beta 类如下:

class Beta(object):
    def __init__(self, alpha=1, beta=1, name=''):
        self.alpha = alpha
        self.beta = beta
        self.name = name

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

__init__() 中配置了 Beta 分布的两个参数 alphabetaupdate() 方法的参数 data 为多次旋转硬币后得到正面和反面的次数,得到 140 次正面和 110 次反面对应参数 (140, 110)

  使用如下代码模拟前述得到 140 次正面和 110 次反面的过程:

beta = Beta()
beta.update((140, 110))
euro.summary()
beta.plot()

输出为:

Maximum likelihood: 56
Mean: 55.95238095238095
Median: 56
Credible Interval (90%): (51, 61)
P(x = 50%) = 0.020976526129544665

图像为:

上面代码使用了 $\alpha = 1$ 和 $\beta = 1$ 的 Beta 分布,相当于均匀分布,所以这里的结果也与使用均匀分布相同。