frequentism-and-bayesianism-chs

频率主义和贝叶斯主义——一个实用的介绍

此notebook最初出现在博客Pythonic Perambulations文章。BSD licensed。

这个系列共4个部分:中文版Part I Part II Part III Part IV,英文版Part I Part II Part III Part IV

科学工作者学习统计学的第一件事儿是要知道有两种不同的方法论:频率主义和贝叶斯主义。尽管这点很重要,但很多科学工作者从来没有机会认识两者的差异,及其产生结果的不同。本文的目的是综合频率主义和贝叶斯主义的理论与实践内容,让科学工作者在数据分析之前做出更好的选择。

开始我将通过理论来论述两者区别,之后用Python代码演示两者在应用中的差异。

频率主义 VS 贝叶斯主义: 理论之争

频率主义与贝叶斯主义的本质之争是对概率定义的差异。

频率主义认为概率是表示有限次的重复测量 。假设我多次测量某个星星的亮度(光量子通量)(F) 时(假设星星通量不会变化),由于测量误差每次得到不同的测量值。在多次测量的前提下,某个变量的频率 指的是测量变量的概率。频率主义认为概率本质上是与频率相关的事件 。因此,一个纯粹的频率主义者会认为,讨论星星真实亮度的概率是没啥意义的,因为真实亮度其实是固定值,也就是说讨论一个固定值的频率分布是瞎扯淡。

贝叶斯理论认为,概率的概念应该被扩展为对一个命题信任的程度 。贝叶斯理论会说测量概率为$P(F)$的星星亮度$F$:虽然概率确实能够通过大量重复实验获取的频率测得,但是这并非频率的本质。概率是一个由个人经验决定测量结果的主观命题。贝叶斯理论认为概率本质上与我们对事件的掌握程度有关 。贝叶斯理论认为人们可以在一个固定的范围内讨论星星真实亮度的概率。概率也会调整我们对先验信息和/或已有数据的认识。(概率会改变常识)

奇怪的是理论争议不大,但是在实际的数据分析中会产生极大差异。下面我会给出一个实际案例的两种理论实现,用Python演示。

频率理论与贝叶斯理论的实际应用: 光量子计量

让我们看一个简单问题,然后比较一下两种方法的差异。这儿得有点儿数学公式,不过我不会入得特别深哈。如果你想深入,你可以考虑一下练练教材4-5章的内容。

研究对象: 简易光量子计量方法

想象一下我们拿着望远镜,观察遥远的星星传来的无尽星光。首先,让我们假设星星的真实亮度是固定值,不会随时间变化。用常量$F_{\rm true}$ 表示(我们还将忽略大气层的影响,以及其他系统性误差)。我们假设用望远镜进行了$N$次测量,第$i^{\rm th}$ 次测量报道了观察到的亮度$F_i$ 和误差$e_i$。

问题是有了这些测量值$D = \{F_i,e_i\}$,真实亮度$F_{\rm true}$的最佳估计值是多少?

(关于测量误差:如果假设测量误差是按正态分布。频率主义者的观点是$e_i$是在大量重复**实验**条件下单次测量的标准差。而贝叶斯理论认为$e_i$是按照我们以往的测量经验描述的(正态)概率分布的标准差。)

我们用Python随机生成一些数据来演示两种理论的差异。由于测量是按次计数的离散事件,我们可以使用泊松分布做演示:

In [1]:
# Generating some simple photon count data
import numpy as np
from scipy import stats
np.random.seed(1)  # for repeatability

F_true = 1000  # true flux, say number of photons measured in 1 second
N = 50 # number of measurements
F = stats.poisson(F_true).rvs(N)  # N measurements of the flux
e = np.sqrt(F)  # errors on Poisson counts estimated via square root

现在让我们为”测量“值做个简单的图形:

In [2]:
get_ipython().magic(u'matplotlib inline')
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.errorbar(F, np.arange(N), xerr=e, fmt='ok', ecolor='gray', alpha=0.5)
ax.vlines([F_true], 0, N, linewidth=5, alpha=0.2)
ax.set_xlabel("Flux");ax.set_ylabel("measurement number");

用标准平方根法则对泊松分布进行分析,可以看到每次测量值的误差都不同。上面的例子中我们是先知道真实值$F_{\rm true}$的,但是实际问题是:只给测量值和误差,怎么找到真实值的最佳估计值?

下面让我们来看看两种理论的不同解决方案。

简易光量子计量的频率主义方法

我们用频率主义中经典的似然估计方法开始。对应某一次测量值$D_i = (F_i, e_i)$,以前面假设的正态分布误差$e_i$为标准差,该事件在真实值$F_{\rm true}$已知的条件下发生的概率分布满足:

$$ P(D_i~|~F_{\rm true}) = \frac{1}{\sqrt{2\pi e_i^2}} \exp{\left[\frac{-(F_i - F_{\rm true})^2}{2 e_i^2}\right]} $$

公式应该读作“在$F_{\rm true}$条件下事件$D_i$发生的概率...”,是个均值$F_{\rm true}$、标准差为$e_i$的正态分布。

我们通过计算每个观测值概率的乘积来构建似然函数

$$\mathcal{L}(D~|~F_{\rm true}) = \prod_{i=1}^N P(D_i~|~F_{\rm true})$$

其中,$D = \{D_i\}$表示整个测量事件。因为似然估计值可能非常小,通常更方便的做法是取对数。

$$\log\mathcal{L} = -\frac{1}{2} \sum_{i=1}^N \left[ \log(2\pi e_i^2) + \frac{(F_i - F_{\rm true})^2}{e_i^2} \right]$$

我们这么做是为了确定$F_{\rm true}$的极大似然估计值。由于问题很简单,所以最大值也容易算(比如通过微分求极值$d\log\mathcal{L}/dF_{\rm true} = 0$)。下面是$F_{\rm true}$的极大似然估计值:

$$ F_{\rm est} = \frac{\sum w_i F_i}{\sum w_i};~~w_i = 1/e_i^2 $$

特殊情况:当所有的测量误差$e_i$相等时,可以推出

$$ F_{\rm est} = \frac{1}{N}\sum_{i=1}^N F_i $$

也就是说,当误差相等时,$F_{\rm est}$等于观测值的期望,这与直觉一致。

我们可以进一步研究下这么估计的误差。按照频率主义方法,可以通过李雅普诺夫定理将最大似然函数的曲线进行正态近似;在这个简单的例子中也可以容易解决。正态近似的标准差是:

$$ \sigma_{\rm est} = \left(\sum_{i=1}^N w_i \right)^{-1/2} $$

这个结果很容易计算;让我们估计一些我们的数据:

In [3]:
w = 1. / e ** 2
print("""
      F_true = {0}
      F_est  = {1:.0f} +/- {2:.0f} (based on {3} measurements)
      """.format(F_true, (w * F).sum() / w.sum(), w.sum() ** -0.5, N))
      F_true = 1000
      F_est  = 998 +/- 4 (based on 50 measurements)
      

可以看出,以50次测量得到的观测值为输入,得出我们的估计误差在千分之4。

简易光量子计量的贝叶斯方法

你可能认为,如果按照贝叶斯方法,通篇都得使用概率计算。我们真正想计算的其实是我们对参数的主观认识,在本例中就是:

$$ P(F_{\rm true}~|~D) $$

可以看出这与频率主义完成相反,要对$F_{\rm true}$这样的固定值建模求解,概率做为模型参数没有任何意义。然而,贝叶斯主义却完全可以接受。

贝叶斯主义使用贝叶斯定理这一基本概率论公式:

$$ P(F_{\rm true}~|~D) = \frac{P(D~|~F_{\rm true})~P(F_{\rm true})}{P(D)} $$

虽然贝叶斯定理这一法则本身没有争议,贝叶斯主义的名字就从那儿来,但是贝叶斯主义对概率有争议的解释却是暗含在法则的$P(F_{\rm true}~|~D)$之中。

让我们仔细看看公式中的术语:

  • $P(F_{\rm true}~|~D)$: 后验概率,是在已获得的数据条件下模型参数的概率:这是我们想要计算的。
  • $P(D~|~F_{\rm true})$: 相似度,与上面频率主义的似然估计$\mathcal{L}(D~|~F_{\rm true})$成正比。
  • $P(F_{\rm true})$: 先验概率,在观察数据$D$之前我们对事件不确定性的认识。
  • $P(D)$: 标准化常量,对实际数量进行简单标准化。

如果我们设置$P(F_{\rm true}) \propto 1$(扁平先验,flat prior),那么会发现

$$P(F_{\rm true}|D) \propto \mathcal{L}(D|F_{\rm true})$$

也就是说贝叶斯主义的概率是频率主义似然估计结果的最大值!因此,遑论两种理论的差异,我们会发现(至少是简单问题)两种估计是等价的。

什么叫先验概率?

你会发现,我为了图省事儿,先验概率$P(F_{\rm true})$没解释清楚。先验概率允许在计算中包含其他有用的信息,实际应用中用多种测量方法组合对某一事件进行评估是非常有用的(比如宇宙成因的参数估计)。然而,确实先验概率的必要性也是贝叶斯分析的争议之一。

当先验事实不存在时,频率主义者会说先验概率不靠谱。尽管用一个未知先验概率更简单,像前面提到那个先验概率常量,但是也会有一些意外的微妙之处。很多实验表明,真正的未知先验概率是不存在的!频率主义者认为主观选择先验概率会偏离结果,不能进行统计数据分析。

贝叶斯主义者认为频率主义解决不了问题,只想简单的避开。在确定(隐含的)先验概率这点上,频率主义经常被简单地看作贝叶斯主义理论的特殊情形:贝叶斯主义会要求最好让隐含变成明确,即使这种选择可能包含主观性。

光量子计量:贝叶斯方法

离开这些理论之争,让我们看看贝叶斯主义的实际计算结果。因为只考虑一个参数,可以将后验概率$P(F_{\rm true}~|~D)$当作$F_{\rm true}$的函数计算:这个分布反映了我们对$F_{\rm true}$分观布主的认识。但是随着模型规模的增长,这种方法就变得难以把握。因此,贝叶斯主义计算方法常常依赖于抽样方法,如蒙特卡罗马尔可夫链(MCMC)

这里不细究MCMC的理论知识,我用Dan Foreman-Mackey的Python emcee包做一个简单的应用。目标是产生一堆满足后验概率分布的点,用这些点来确定我们问题的答案。

要演示MCMC,我们用Python定义先验概率$P(F_{\rm true})$,似然估计值$P(D~|~F_{\rm true})$,以及后验概率$P(F_{\rm true}~|~D)$。我们的模型是一维的,但是为了处理多维模型,我们要定义参数数组$\theta$,在我们的例子中就是$\theta = [F_{\rm true}]$:

In [4]:
def log_prior(theta):
    return 1  # flat prior

def log_likelihood(theta, F, e):
    return -0.5 * np.sum(np.log(2 * np.pi * e ** 2)
                         + (F - theta[0]) ** 2 / e ** 2)

def log_posterior(theta, F, e):
    return log_prior(theta) + log_likelihood(theta, F, e)

现在我们开始解决问题,产生随机数来猜测这些马尔可夫链上的点。

In [5]:
ndim = 1  # number of parameters in the model
nwalkers = 50  # number of MCMC walkers
nburn = 1000  # "burn-in" period to let chains stabilize
nsteps = 2000  # number of MCMC steps to take

# we'll start at random locations between 0 and 2000
starting_guesses = 2000 * np.random.rand(nwalkers, ndim)

import emcee
sampler = emcee.EnsembleSampler(nwalkers, ndim, log_posterior, args=[F, e])
sampler.run_mcmc(starting_guesses, nsteps)

sample = sampler.chain  # shape = (nwalkers, nsteps, ndim)
sample = sampler.chain[:, nburn:, :].ravel()  # discard burn-in points

如果都能正常运行,数值sample会包含满足后验概率分布的50000个点。让我们画出来看看:

In [6]:
# plot a histogram of the sample
plt.hist(sample, bins=50, histtype="stepfilled", alpha=0.3, normed=True)

# plot a best-fit Gaussian
F_fit = np.linspace(975, 1025)
pdf = stats.norm(np.mean(sample), np.std(sample)).pdf(F_fit)

plt.plot(F_fit, pdf, '-k')
plt.xlabel("F"); plt.ylabel("P(F)")
Out[6]:
<matplotlib.text.Text at 0x7f061dec3f90>

我们从(正态)后验概率分布得到一样本。后验概率的期望和标准差是由前面的频率主义极大似然估计得来的:

In [7]:
print("""
      F_true = {0}
      F_est  = {1:.0f} +/- {2:.0f} (based on {3} measurements)
      """.format(F_true, np.mean(sample), np.std(sample), N))
      F_true = 1000
      F_est  = 998 +/- 4 (based on 50 measurements)
      

可以看出,在简单情况下,贝叶斯主义和频率主义两种方法的结果相同!

分析

现在,你可能认为贝叶斯主义的复杂性没啥必要,这个例子已经充分证明了。其实,用一个仿射不变MCMC综合样本发生器来模拟这样一个简单的一维正态分布,实在是杀鸡用牛刀,但是这么做的目的是要表明该方法同样适用于多维度的复杂后验概率情形,也能在复杂条件下提供似然估计不可能提供的优美的结果。

另外,你还可能注意到一个小伎俩:最后,我们用来频率主义方法来描述后验概率样本!当我们计算样本期望和标准差的时候,我们使用了一个标准的频率主义方法来刻画后验概率分布。用纯贝叶斯理论分析这个问题的结果可能要包含后验概率本身(比如,它的类似样本)。也就是说,在纯贝叶斯主义的结果中,问题不是一个简单的数值和误差,而是后验概率分布和模型参数!

增加一个维度:研究更复杂的模型

让我们看一个更复杂的情况,再比较一下频率主义和贝叶斯主义的结果。前面我们假设星星是静止的,现在假设我们观察的天体是一个随机变量;就是说它会随着时间变化(就是类星体那种)。

我们将用双参数正态分布来表示这个天体:$\theta = [\mu, \sigma]$,其中,$\mu$是期望值,$\sigma$是天体本征变量的标准差。于是我们每次观察时真实亮度概率的模型:

$$ F_{\rm true} \sim \frac{1}{\sqrt{2\pi\sigma^2}}\exp\left[\frac{-(F - \mu)^2}{2\sigma^2}\right]$$

现在,我们再考虑$N$次观察里每次的误差。可以这么产生:

In [8]:
np.random.seed(42)  # for reproducibility
N = 100  # we'll use more samples for the more complicated model
mu_true, sigma_true = 1000, 15  # stochastic flux model

F_true = stats.norm(mu_true, sigma_true).rvs(N)  # (unknown) true flux
F = stats.poisson(F_true).rvs()  # observed flux: true flux plus Poisson errors.
e = np.sqrt(F)  # root-N error, as above

可变条件下的光量子计量:频率主义方法

似然估计结果是本征分布与误差分布的卷积,可以得出

$$\mathcal{L}(D~|~\theta) = \prod_{i=1}^N \frac{1}{\sqrt{2\pi(\sigma^2 + e_i^2)}}\exp\left[\frac{-(F_i - \mu)^2}{2(\sigma^2 + e_i^2)}\right]$$

与前面类似,我们可以通过求微分解出似然估计的最大值,即$\mu$的最佳估计:

$$\mu_{est} = \frac{\sum w_i F_i}{\sum w_i};~~w_i = \frac{1}{\sigma^2 + e_i^2} $$

这里有个问题:参数$\mu$的值依赖于$\sigma$的值。两者具有相关性,因此我们不能直接使用频率主义的解析方法求解。

然而,我们能用数值分析计算来解极大似然估计值。这里我们用Scipy里面的最优化工具optimize

In [9]:
def log_likelihood(theta, F, e):
    return -0.5 * np.sum(np.log(2 * np.pi * (theta[1] ** 2 + e ** 2))
                         + (F - theta[0]) ** 2 / (theta[1] ** 2 + e ** 2))

# maximize likelihood <--> minimize negative likelihood
def neg_log_likelihood(theta, F, e):
    return -log_likelihood(theta, F, e)

from scipy import optimize
theta_guess = [900, 5]
theta_est = optimize.fmin(neg_log_likelihood, theta_guess, args=(F, e))
print("""
      Maximum likelihood estimate for {0} data points:
          mu={theta[0]:.0f}, sigma={theta[1]:.0f}
      """.format(N, theta=theta_est))
Optimization terminated successfully.
         Current function value: 502.839505
         Iterations: 58
         Function evaluations: 114

      Maximum likelihood estimate for 100 data points:
          mu=999, sigma=19
      

Scipy给出了$\mu$和$\sigma$的极大似然估计值的最佳组合。但是问题才解决一半:我们需要确定答案的置信区间,也就是我们要计算$\mu$和$\sigma$的误差。

在频率主义模式中有不同的方法来确定误差。如前所述,我们可以用正态近似去拟合最大似然估计和协方差矩阵(这里我们应该用数值分析而不是解析方法)。另外,我们可以计算统计量如$\chi^2$和$\chi^2_{\rm dof}$,然后使用卡方检验来决定置信区间,还需要假设似然估计具有正态性。我们也可以使用随机抽样方法如Jackknife或者Bootstrap,为了研究结果的确定程度,使输入数据的随机样本的似然估计最大化。

这些方法都行,但是每种方法都有各自的假设前提和特点。我们用Python的astroML包里面的basic bootstrap resampler:

In [10]:
from astroML.resample import bootstrap

def fit_samples(sample):
    # sample is an array of size [n_bootstraps, n_samples]
    # compute the maximum likelihood for each bootstrap.
    return np.array([optimize.fmin(neg_log_likelihood, theta_guess,
                                   args=(F, np.sqrt(F)), disp=0)
                     for F in sample])

samples = bootstrap(F, 1000, fit_samples)  # 1000 bootstrap resamplings

和前面的贝叶斯后验概率的MCMC方法类似,我们将计算样本期望值和标准差来确定参数误差。

In [11]:
mu_samp = samples[:, 0]
sig_samp = abs(samples[:, 1])

print " mu    = {0:.0f} +/- {1:.0f}".format(mu_samp.mean(), mu_samp.std())
print " sigma = {0:.0f} +/- {1:.0f}".format(sig_samp.mean(), sig_samp.std())
 mu    = 999 +/- 4
 sigma = 18 +/- 5

我得说明bootstrap resampling的细究有大堆资料可供参考,这里粗略地说明一下这个方法的特点。最明显的地方就是误差需要是相关的、非正态的,但是这两个特点都不能通过简单的计算每个模型参数的均值和方差反映出来。然而,我相信这给频率主义提供的基本的解题思路。

可变条件下的光量子计量:贝叶斯主义方法

贝叶斯主义对这个问题的解决方法可之前那个问题基本雷同,我们可以把上面的代码简单改改就行。

In [12]:
def log_prior(theta):
    # sigma needs to be positive.
    if theta[1] <= 0:
        return -np.inf
    else:
        return 0

def log_posterior(theta, F, e):
    return log_prior(theta) + log_likelihood(theta, F, e)

# same setup as above:
ndim, nwalkers = 2, 50
nsteps, nburn = 2000, 1000

starting_guesses = np.random.rand(nwalkers, ndim)
starting_guesses[:, 0] *= 2000  # start mu between 0 and 2000
starting_guesses[:, 1] *= 20    # start sigma between 0 and 20

sampler = emcee.EnsembleSampler(nwalkers, ndim, log_posterior, args=[F, e])
sampler.run_mcmc(starting_guesses, nsteps)

sample = sampler.chain  # shape = (nwalkers, nsteps, ndim)
sample = sampler.chain[:, nburn:, :].reshape(-1, 2)

现在有了样本,我们可以利用astroML包方便的功能来画出轨迹图,并用等高线描述1、2标准差的情况:

In [13]:
from astroML.plotting import plot_mcmc
fig = plt.figure()
ax = plot_mcmc(sample.T, fig=fig, labels=[r'$\mu$', r'$\sigma$'], colors='k')
ax[0].plot(sample[:, 0], sample[:, 1], ',k', alpha=0.1)
ax[0].plot([mu_true], [sigma_true], 'o', color='red', ms=10);

红点显示在真实值附近(在前述问题条件下),等高线显示了1、2个标准差的置信区间情况(68%和95%置信水平)。

这里要注意$\sigma = 0$与两个标准差的情况一致:也就是说,依赖于你自己对确定性的临界值感觉,我们的数据不足以保证一个定点数据源概率的置信区间。

另外,后验概率确实是正态的:可以通过垂直方向的对称性来看。也就意味着用频率主义的正态近似不会将真实的不确定性反映到结果中。对频率主义者来说这不是啥事儿(频率主义模式有方法会考虑到非正态性),但是频率主义方法的绝大多数使用者都直接或间接地使用了正态分布的假设。贝叶斯方法一般不需要这个假设。

(先验概率:有些观点在确定$\sigma$的扁平先验时与本文的计算方式有轻微差异:它们认为,在处理像$\sigma$这样的比例因子时,扁平先验不是必须的。[Jeffreys 先验](http://en.wikipedia.org/wiki/Jeffreys_prior)的一些有趣的论述更容易接受。我认为Jeffreys不太适合,因为$\sigma$不是一个真实的比例因子(比如,正态分布也会影响$e_i$)。关于这个问题,我将参考其他专业人士的观点。我个人认为,这些小问题往往是贝叶斯主义与频率主义争论的焦点)。

结论

我希望我已经通过这篇文章展示了频率主义与贝叶斯主义根本的区别,导致两者本质上对同样问题有着不同的解释,然而彼此却经常可以产生相似甚至相同的结果。

两者差异总结如下:

  • 频率主义认为概率与事实或假想事件的频率有关。
  • 贝叶斯主义认为概率是对事件认识程度的度量。
  • 频率主义通常使用点估计和极大似然估计方法进行分析。
  • 贝叶斯主义通常直接的计算后验概率,或者通过一些MCMC抽样的方法计算。

处理简单问题时,两种方法会产生近似的结果。但当数据和模型越来越复杂时,两种方法会有天壤之别。在以后的文章中,我会显示一两个更复杂的案例。继续关注噢!

Update: 看下一篇文章:频率主义与贝叶斯主义 II: 当结果不同时