马尔可夫链蒙特卡罗(MCMC)是一类功能强大的方法,用于从已知直到(未知)归一化常数的概率分布中进行抽样。但是在我们深入研究MCMC之前,让我们先来考虑一下为什么您可能首先想要进行采样。
这个问题的答案是:只要你对样本本身感兴趣(例如,在贝叶斯推理中推断未知参数),或者你需要它们来近似函数的期望值w.r.t。对于概率分布(例如,从统计物理中的微态分布计算热力学量),有时只有概率分布的模式是主要感兴趣的。在这种情况下,它是通过数值优化获得的,所以不需要全抽样。
事实证明,除了最基本的概率分布外,对任何概率分布进行抽样都是一项艰巨的任务。逆变换抽样是从概率分布中抽样的一种基本方法,但需要累积分布函数,而累积分布函数又需要知道通常未知的归一化常数。现在原则上,您可以通过数值积分来获得归一化常数,但随着维数的增加,这很快就不可行了。拒绝抽样不需要归一化分布,但有效地实现它需要大量关于兴趣分布的知识,而且它强烈地受到维数诅咒的影响,这意味着它的效率随着变量数量的增加而迅速下降。这就是当你需要一种智能的方法从你的分布中获得具有代表性的样本时,这种方法不需要知道归一化常数。
MCMC算法就是这样一类方法,这些方法可以追溯到Metropolis等人的一篇开创性的论文,他们提出了第一个MCMC算法,相应地称为Metropolis算法,用于计算二维硬球系统的状态方程。实际上,他们正在寻找一种通用的方法来计算统计物理中出现的期望值。
在这篇博客文章中,我介绍了MCMC采样的基础知识;在随后的文章中,我将介绍几个重要的、日益复杂和强大的MCMC算法,这些算法都解决了人们在使用Metropolis-Hastings算法时经常面临的不同困难。在此过程中,您将对这些挑战以及如何解决这些挑战有一个坚实的理解。同时,这也可以作为Monad-Bayes系列中MCMC方法的参考。此外,我希望提供的笔记本不仅能激发您探索各种参数/概率分布的MCMC算法行为的兴趣,而且还可以作为实现和理解我所介绍的算法基本版本的有用扩展的基础。
现在我们知道为什么要采样了,让我们来看看MCMC的核心:马尔可夫链。什么是马尔可夫链?在没有所有技术细节的情况下,马尔可夫链是某个状态空间中的一个随机状态序列,在这个序列中,下一个选择某个状态的概率只取决于链中的当前状态,而不取决于之前的历史:它是无记忆的,在一定条件下,马尔可夫链在一定数量的状态之后收敛到唯一的平稳状态分布。从这个数字开始,马尔可夫链中的状态根据不变分布分布。
为了从分布π(X)\pi(X)π(X)中采样,MCMC算法构造并模拟其平稳分布为π(X)\pi(X)π(X)的马尔可夫链,这意味着,在初始“老化”阶段之后,该马尔可夫链的状态是按照π(X)\pi(X)π(X)分布的,因此我们只需存储状态就可以从π(X)\pi(X)π(X)中获得样本。
出于说教的目的,现在让我们同时考虑离散的状态空间和离散的“时间”。表征马尔可夫链的关键量是转移算子T(xi+1|xi)T(xi+1}|xi)T(xi+1|xi),它给出了你在某一时刻处于状态xi+1x{i+1}xi+1的概率。假设链在时间i i处处于状态xi x_i x i,则i+1i+1i+1。
现在,为了好玩(也是为了说明),让我们快速构建一个具有唯一平稳分布的马尔可夫链。我们将从一些绘图的导入和设置开始:
马尔可夫链将在由三种天气状态组成的离散状态空间上跳跃:
在离散状态空间中,转换运算符只是一个矩阵。在我们的示例中,列和行对应于晴天、多云和下雨的天气。我们为所有转换概率选择或多或少合理的值:
这些行表示链当前可能处于的状态以及链可能转换到的列。如果我们将马尔可夫链的一个“时间”步骤作为一个小时,那么,如果是晴天,那么在接下来的一个小时里有60%的可能性保持晴朗,30%的可能性在下一个小时我们会有多云的天气,只有10%的可能性在之前晴朗之后立即下雨。这也意味着每一行的总和必须是1。
我们可以通过计算每个状态的经验概率作为链长的函数来监控马尔可夫链向其平稳分布的收敛:
Def Despine(ax,spines=(';top';,';left';,';right';)):对于脊椎中的脊椎:ax.spines[spines].SET_Visible(False)Figure,ax=PLT.subplots()width=1000offsets=range(1,n_step,5)for i,枚举中的标签(State_Space):ax.lot(偏移,[np.。SUM(STATES[:OFFSET]==I)/偏移量的偏移量],LABEL=LABEL)ax.SET_xlabel(";步数";)ax.SET_ylabel(";似然度";)ax.Legend(FRAMON=FALSE)Despine(ax,(';top';,';right';))plt.show()。
这很有趣,但回到采样任意概率分布π\piπ,它可以是离散的,在这种情况下,我们会继续讨论转移矩阵T T,也可以是连续的,在这种情况下,T将是转移核,从现在开始,我们考虑的是连续分布,但这里给出的所有概念都转移到离散的情况。
如果我们可以这样设计转换核,即下一个状态已经从π\piπ中提取出来,我们就可以这样做了,就像我们的马尔可夫链将…一样。Well…。立即从π\piπ获取样本。不幸的是,要做到这一点,我们需要能够从π\piπ获取样本,但我们无法做到这一点。否则您不会阅读本文,对吗?
一种绕过此问题的方法是将转移核T(xi+1|xi)T(xi+1}|xi)T(xi+1|xi)分成两部分:提议步骤和接受/拒绝步骤,该提议步骤以提议分布Q(xi+1|xi)Q(xi+1}|xi)Q(x。I+1|x i),我们可以从中取样链的可能的下一种状态,除了可以从中取样外,我们还可以任意选择这个分布。但,。Said接受/拒绝步骤是转换核的第二部分,用于校正从q≠πq\neq\pi q=π得出的建议状态所引入的错误。它涉及计算接受概率p a c(x i+1|x i)p_\mathm{acc}(xi/pi)。该步骤包括计算接受概率p a c(x i+1|x i)p_\mathm{acc}(xi/pi)。它包括计算接受概率p a c(xi+1|x i)p_\mathm{acc。_{i+1}|xi_i)p a c c(xi+1|xi),并接受具有该概率的提议xi+1 x_{i+1}xi+1作为链中的下一个状态。从T()绘制下一个状态xi+1 x_{i+1}xi i+1(。然后如下进行xi+1|xi)T(xi_{i+1}|xi_i)T(xi+1|xi):首先,从q(xi+1|xi)q(xi+1}|xi)q(xi+1|xi)q(xi+1|xi)中提取出一个建议状态xi+1x{i+1}xi+1 acc,并以概率p a c(xi+1|xi)p\mathm{acc}接受。(x_{i+1}|x_i)p a c c(xi+1|x i)或以概率1−p a c c(x_i+1|xi)1-p_\mathm{acc}(x\_i+1}|xi_i)1−p a c(xi+1|xi)被拒绝,在这种情况下,当前状态被复制为下一状态。
T(xi+1|xi)=q(xi+1|xi)×p a c c(xi+1|xi)。T(x_{i+1}|x_i)=q(x_{i+1}|x_i)\x p_\mathm{acc}(x_{i+1}|x_i)\\text。T(xi+1|xi)=q(xi+1|xi)×p a c c(xi+1|xi)。马尔可夫链具有π\piπ作为其平稳分布的一个充分条件是符合详细平衡的转移核,或者在物理学文献中,是微观可逆性:
π(Xi)T(xi+1|xi)=π(xi+1)T(xi|xi+1)\pi(Xi)T(xi+1}|xi)=\pi(xi+1})T(xi|xi+1})π(xi)T(xi+1|xi)=。π(x i+1)T(x i|x i+1)这意味着处于状态x i x_i x i并转变到x i+1x_{i+1}x i+1的概率必须等于反向过程的概率,即处于x_i+1x_i+1}x_i+1状态并转换到x_i_i x_i状态,大多数MCMC算法的转换核都满足这一条件。
为了使两部分过渡核遵循详细平衡,我们需要正确选择p a c c p\mathm{acc}p a c c,这意味着必须校正从/到x i+1 x_{i+1}x i+1或x i x_i x i的概率流中的任何不对称。Metropolis-Hastings使用Metropolis-Hastings标准:
P a c c(xi+1|xi)=m in{1,π(xi+1)×q(xi|xi+1)π(Xi)×q(xi+1|xi)}n。P_\mathm{acc}(x_{i+1}|x_i)=\mathm{min}\Left\{1,\frac{\pi(x_{i+1})\x q(x_i|x_{i+1})}{\pi(X_I)\x q(x_{i+1}|x_i)}\right\}\\text。P a c c(xi+1|xi)=m in n{1,π(x i)×Q(x i+1|x i)π(xi+1)×Q(x i|xi+1)}))。这里是魔术发生的地方:我们知道π\piπ最多只有一个常数,但这并不重要,因为这个未知的常数在p a c c p\mathm{acc}p a c的表达式中被抵消了!正是p a c c p\mathm{acc}p a c的这个性质使得基于Metropolis-Hastings的算法适用于非正规化分布。通常,使用具有q(xi|xi+1)=q(xi+1|xi)q(xi|xi+1})=q(xi+1}|xi)q(xi|xi+1)=q(xi+1|xi)的对称建议分布,在这种情况下,Metropolis-Hastings算法简化为1953年开发的原始但不太通用的Metropolis算法。
P a c c(xi+1|x
现在,我们将所有这些整合到我们真正简短的Metropolis-Hastings抽样步骤中:
Def SAMPLE_MH(x_old,log_prob,stepsize):x_new=proposal(x_old,stepsize)#这里我们确定是否接受新状态:#我们从[0,1]均匀抽取一个随机数,并将其与接受概率Accept=nP.Random()<;p_acc(x_new,x_old,log_prob)if Accept:Return Accept,x_new Else:Return Accept,x_old。
除了马尔可夫链中的下一个状态x_new或x_old之外,我们还返回MCMC移动是否被接受。这将允许我们跟踪接受率。让我们通过编写一个迭代调用SAMPLE_MH从而建立马尔可夫链的函数来完成我们的实现:
Def build_MH_chain(init,stepsize,n_total,log_prob):n_Accept=0 chain=[init]for_in range(N_Total):Accept,state=Sample_MH(chain[-1],log_prob,stepsize)chain.追加(状态)n_Accept+=Accept Accept_Rate=n_Accept/Float(N_Total)返回链,Accept_Rate。
现在您可能会很兴奋地看到这一点的实际操作。下面,让我们对步长和n_total参数进行一些有见地的猜测:
CHAIN,ACCEPTION_RATE=BUILD_MH_CHAIN(NP.array([2.0]),3.0,10000,LOG_PROB)CHAIN=[STATE FOR STATE,IN CHAIN]PRINT(";接受率:{:.3f}";。Format(Accept_Rate))LAST_STATES=";,";.Join(";{:.5f}";。链中状态的格式(状态)[-10:])打印(";链的最后十个状态:";+LAST_STATES)。
合格率:0.722链条最近十种状态:-0.84962、-0.84962、-0.84962、-0.08692、0.92728、-0.46215、0.08655、-0.33841、-0.33841、-0.33841。
好的。那么这个工作做了吗?我们达到了大约71%的接受率,我们有一个状态链。我们应该扔掉链还没有收敛到它的稳定分布的最初几个状态。让我们检查一下我们画的状态是否实际上是正态分布:
定义PLOT_SAMPLES(CHAIN,LOG_PROB,AX,Orientation=';垂直';,Normize=True,xlims=(-5,5),Legend=True):从scipy.Integrate导入quad ax.hist(CHAIN,BINS=50,Density=True,Label=";MCMC Samples";,Orientation=Orientation)#如果归一化,我们数值计算PDF的归一化常数:z,_=quad(lambda x:np.exp(log_prob(X)),-np.inf,np.inf)否则:z=1.0 xses=np.linspace(xlims[0],xlims[1],1000)yses=[np.exp(log_prob(X))/Z for x in xse]if Orientation==';水平';用法:(yses,xses)=(xses,yses)ax.lot(xses,yses,label=";true Distribution";)如果图例:ax.legend(frame on=false)fig,ax=plt.subplots()lot_sample(chain[500:],log_prob,ax)Despine(Ax)ax.set_yticks(())plt.show()。
现在,参数stepsize和n_total有什么问题?我们将首先讨论步长:它确定建议状态与链的当前状态之间的距离。因此,它是建议分布q q的一个参数,并控制马尔可夫链采取的随机步长有多大。如果步长太大,建议状态通常位于分布的尾部,概率较低。Metropolis-Hastings采样器拒绝大多数这些移动,这意味着接受率降低,收敛速度变慢。您自己看一下:
Def sample_and_display(init_state,stepsize,n_total,n_burnin,log_prob):chain,Accept_Rate=build_MH_chain(init_state,stepsize,n_total,log_prob)print(";接受率:{:.3f}";。FORMAT(Accept_Rate))图,ax=PLT.subplots()PLOT_SAMPLES([STATE FOR STATE,in chain[n_burnin:]],LOG_PROB,AX)Despine(AX)ax.set_yticks(())PLT.show()SAMPLE_AND_DISPLAY(NP.array([2.0]),30,10000,500,LOG_PROB)。
不是很酷,对吧?现在你可能认为最好的做法是选择一个很小的步长。结果发现,这也不是太聪明,因为那样马尔可夫链只会非常慢地探索概率分布,因此也不会像调整好的步长那样快速收敛:
无论您如何选择步长参数,马尔可夫链最终都会收敛到它的平稳分布。但这可能需要很长时间。我们模拟马尔可夫链的时间由n_total参数设置-它只决定我们将得到多少个马尔可夫链(以及样本)的状态。如果链收敛很慢,我们需要增加n_total,以便让马尔科夫链有足够的时间忘记其初始状态。因此,让我们保持最小的步长,并通过增加n_total来增加样本数:
有了这些考虑,我结束了本系列的第一篇博客文章,我希望您现在理解Metropolis-Hastings算法背后的直觉、它的参数,以及为什么它是从您在野外可能遇到的非标准概率分布中抽样的一个极其有用的工具。
我强烈建议您尝试使用此笔记本中提供的代码-这样,您就可以了解算法在各种情况下是如何运行的,并加深您对它的理解。继续尝试非对称提案分布!如果您没有相应地调整接受标准会发生什么?如果您试图从双峰分布中采样会发生什么?您能想出一种自动调整步长的方法吗?这里有哪些陷阱?尝试一下。
.