import numpy as np
import matplotlib.pyplot as plt
3 用分布来解决问题
3.1 重拾红球与白球问题
我们知道:
\[\text{Posterior distribution} \propto \text{Prior distribution} \times \text{Likelihood distribution}\]
\(\propto\) 意思是 proportional to,a 与 b 成比例。之所以「成比例」而不是「等于」是因为 prior 与 likelihood 相乘的结果是未标准化的 posterior。
我们还拿 Section 2.1 用到的红球与白球来举例:
def normalize_array(arr):
return np.array([i/sum(arr) for i in arr])
= np.array([0.5, 0.5])
prior prior
array([0.5, 0.5])
# Likelihood: 某 hypothesis 的情况下,该 data 的概率
# 在这里,hypothesis 是哪一个碗,data 是我们随机抽一个球,抽到了红球
= np.array([0.75, 0.5])
likelihood_red = normalize_array(prior * likelihood_red)
posterior posterior
array([0.6, 0.4])
现在我问你,假如我们把这颗红球放进去,在同一只碗中随机抽球,又抽到一颗红球,那这颗红球来自两只碗的概率分别是多少?
我们先来看另一个不一样的:
假如我们把这颗红球放进去,再随机拿一只碗,随机抽球,又抽到一颗红球,那这颗红球来自两只碗的概率分别是多少?因为是 随机 拿一只碗,那么这一次抽到红球的情况和第一次是一样的,prior 和 likelihood 是一样的,因此 posterior 也是一样的。
但我们现在是在同一只碗中随机抽球,prior (碗是哪只碗)不再是对半开了。因为第一次抽完后,我们知道这颗红球来自碗一的概率是 \(0.6\),来自碗二的概率是 \(0.4\)。
第二次是在「同一只碗」中随机抽球,那这只碗是哪只碗,也就是 prior,是第一次抽中红球的 posterior。而第二次时的 likelihood 保持不变。
因此:
*= likelihood_red
posterior = normalize_array(posterior)
posterior posterior
array([0.69230769, 0.30769231])
好,我们继续。第三次,把球放回,在同一只碗 中继续抽,抽到一颗白球,那这颗白球分别来自两只碗的概率是多少?
第三次的 prior 依然是「同一只碗」是哪只碗的问题,也就是第二次的 posterior。Likelihood 变了,变成了 likelihood_white
。我们接着计算:
= np.array([0.25, 0.5])
likelihood_white *= likelihood_white
posterior = normalize_array(posterior)
posterior posterior
array([0.52941176, 0.47058824])
3.2 一百零一只碗
我们现在有 101 只碗,标号分别为 0 到 100
- 碗 0 中 0% 是红球
- 碗 1 中 1% 是红球
- 碗 2 中 2% 是红球
… - 碗 99 中 99% 是红球
- 碗 100 中 100% 是红球
每一只碗中不是红球就是白球。我们随机抽一只碗,从中随机抽一个球,抽到了一颗红球,请问这颗红球来自碗 \(x\) 的概率是多少?
我们来分析:
- hypothesis: 碗 \(x\)
- data: 随机抽一只碗,随机抽一颗球,抽到了红球
- prior: \(p(h)\)
- likelihood: \(p(d|h)\)
- posterior: \(p(h|d)\)
= 101
n # uniform prior:
= [1]*n
all_ones = normalize_array(all_ones)
prior # likelihood array:
= np.array([i/(n-1) for i in range(n)])
likelihood_red = normalize_array(prior * likelihood_red)
posterior 0:5] posterior[
array([0. , 0.00019802, 0.00039604, 0.00059406, 0.00079208])
Code
= range(n)
x_axis = x_axis, y = prior,
plt.scatter(x ="prior", color="orange", s = 2)
label= x_axis, y = posterior,
plt.scatter(x ="posterior", color="steelblue", s = 2)
label"Bowl #")
plt.xlabel("Probability mass function")
plt.ylabel(
plt.legend()"Posterior after one red ball")
plt.title( plt.show()
假如我们把红球放回,从 同一只碗 中再次随机抽球,我们又抽到了一颗红球,请问这第二颗红球来自碗 \(x\) 的概率是多少?
Code
= normalize_array(posterior * likelihood_red)
posterior2 = x_axis, y = posterior2,
plt.scatter(x ="posterior2", color="purple", s = 2)
label"Bowl #")
plt.xlabel("Probability mass function")
plt.ylabel(
plt.legend()"Posterior after two red balls")
plt.title( plt.show()
接着,我们把红球放回,在同一只碗 中再次随机抽球,这次我们抽到了一颗白球,请问这第三颗白球来自碗 \(x\) 的概率是多少?
这时的 prior 仍是关于「碗」的。这里说了是「同一只碗」,但我们并不确定同一只碗到底是哪只碗,这是由第二次抽取决定的。第二次的 posterior 就是我们这次的 prior。
Code
= np.array([1 - x for x in likelihood_red])
likelihood_white = normalize_array(posterior2 * likelihood_white)
posterior3 = x_axis, y = posterior3,
plt.scatter(x ="posterior3", color="green", s = 2)
label"Bowl #")
plt.xlabel("Probability mass function")
plt.ylabel(
plt.legend()"Posterior after 2 red, 1 white")
plt.title( plt.show()
这里,PMF (probability mass function) 的最高点叫做 “maximum a posterior probability” (MAP).
如果我们想知道这里的最高点是哪一只碗:
= np.argmax(posterior3)
max_index print("最高点出现在碗 #", max_index)
最高点出现在碗 # 67
3.3 顺序重要吗?
我们看到 posterior3
是如此得出的:
= [1]*n
all_ones = normalize_array(all_ones)
prior = normalize_array(prior * likelihood_red)
posterior = normalize_array(posterior * likelihood_red)
posterior2 = normalize_array(posterior2 * likelihood_white) posterior3
我们注意到每次我们都用到了 normalize_array()
,但这大可不必,只需要最后一次即可。我们甚至连
all_ones = [1]*n
prior = normalize_array(all_ones)
都没必要。
这里 prior
, likelihood_red
, likelihood_white
, 和每个 posterior
都是一组数 (array)。
另外,如果抽到的顺序不是 红-红-白,而是白-红-红,结果会一样。
总结来说,我们需要证明的是上面算出来的 posterior3 和下面算出来的应该是一样的:
posterior3_new = all_ones * likelihood_white * likelihood_red * likelihood_red # 顺序变了
posterior3_new = normalize_array(posterior3_new) # 只最后标准化一次,中间没有
那我们就来看一下:
0:5] posterior3[
array([0.00000000e+00, 1.18811881e-05, 4.70447045e-05, 1.04770477e-04,
1.84338434e-04])
= all_ones * likelihood_white * likelihood_red * likelihood_red
posterior3_new = normalize_array(posterior3_new)
posterior3_new 0:5] posterior3_new[
array([0.00000000e+00, 1.18811881e-05, 4.70447045e-05, 1.04770477e-04,
1.84338434e-04])
sum(np.isclose(posterior3, posterior3_new)) == len(prior)
True
这就说明,顺序不重要:红-红-白 与 红-白-红、白-红-红 的结果是一样的。
3.4 总结
我们把一百零一只碗这个问题泛化一下。
假设我们总共有 \(n+1\) 只碗:
- 碗 0 中 0/n 是红球
- 碗 1 中 1/n 是红球
- 碗 2 中 2/n 是红球
… - 碗 n 中 n/n 是红球
每一只碗中不是红球就是白球,且每只碗中球的总数相同。我们随机取一只碗,有放回地在这只碗中抽取球。我们把事件 T 定义为:
共抽取 m 次,其中抽中红球 r 次,白球 w 次
那么事件 T 发生的概率是多少?
def update_bowls_pmf(n, r, w):
"""
n: 总共几只碗
r: 红球
w: 白球
"""
= np.array([1]*n)
priors = normalize_array(priors)
priors = np.array([i/(n-1) for i in range(n)])
likelihood_red = np.array([1- i for i in likelihood_red])
likelihood_white = {
likelihood "red": likelihood_red,
"white": likelihood_white
}= ["red"]*r + ["white"]*w
dataset for data in dataset:
*= likelihood[data]
priors
= normalize_array(priors)
posterior return posterior
= update_bowls_pmf(n=101, r=2, w=1)
new_posterior 0:5] new_posterior[
array([0.00000000e+00, 1.18811881e-05, 4.70447045e-05, 1.04770477e-04,
1.84338434e-04])
# 我们来检测一下 红-红-白 是否和最原始的计算结果一致:
= update_bowls_pmf(n=101, r=2, w=1)
new_posterior sum(np.isclose(new_posterior, posterior3_new)) == len(prior)
True
3.5 揭晓面纱
你可能会问,上面的方法有什么用。那我问你另一个问题。假设,我不告诉你这些碗,只说这些:
从一只装有红球和白球的碗中,随机有放回地抽球,每次抽一颗,抽了三次,这三次的结果是:红球,红球,白球。请问这只碗中的红球比例最有可能是多少?
你就会知道,上面的结果可以回答这个问题。
当然你也可以如此解决:
def y(x):
# 假设红球比例是x
return x**2*(1-x)
= np.linspace(0, 1, 100)
x
plt.plot(x, y(x))"Proportion of red balls")
plt.xlabel("Probability that the above mentioned event occurred")
plt.ylabel(0, 1)
plt.xlim( plt.show()
from scipy.optimize import minimize_scalar
def y(x):
return -x**2*(1-x)
= minimize_scalar(y, bounds=(0,1), method="bounded")
result result
message: Solution found.
success: True
status: 0
fun: -0.14814814814787028
x: 0.666666139518174
nit: 10
nfev: 10
# 所以结果是:
= -result.fun
max_value = result.x
optimal_x optimal_x, max_value
(0.666666139518174, 0.14814814814787028)
也就是说,当红球比例是 \(66.7\%\) (也就是 \(\frac{2}{3}\)) 时,上述事件发生的概率最高。
这和我们上面得到的 \(67\%\) 是一个道理:这三颗球来自碗 67 的概率最高。这也就是说,这三颗球来自红球比例为 \(67\%\) 的那只碗的概率最高。
其实这和我们的直觉是一样的,因为三次的结果是两次为红球,那最有可能红球的比利是三分之二。