我试图自动化一个过程,在某些时候需要从截断的多元正态分布中抽取样本。也就是说,它是一个正常的多元正态分布(即。高斯),但变量被约束到一个长方体。我给出的输入是完整的多元正态分布的均值和协方差,但我需要在我的盒子里有样本。
到目前为止,我只是在框外拒绝样本,并在必要时重新排序,但我开始发现我的过程有时会给我(a)大的协方差和(b)接近边缘的均值。这两件事合在一起影响了我的系统的速度。
所以我想做的是首先正确地对分布进行采样。谷歌搜索只导致了这个讨论或scipy.stats
中的truncnorm
发行版。前者是不确定的,后者似乎是一个变量。是否存在任何原生的多元截断正态分布?这会比拒绝样本更好吗?或者我应该做些更聪明的事情?
我将开始研究我自己的解决方案,这将是将未截断的高斯旋转到它的主轴(使用SVD分解或其他方法),使用截断高斯的乘积对分布进行采样,然后将该样本旋转回来,并在必要时拒绝/重新采样。如果截尾采样更有效,我认为这应该更快地采样所需的分布。
5条答案
按热度按时间balp4ylt1#
因此,根据the Wikipedia article,对多元截断正态分布(MTND)进行采样更加困难。我最终采取了一种相对简单的方法,并使用MCMC采样器放松了对MTND的初步猜测,如下所示。
我使用emcee来做MCMC工作。我发现这个软件包非常容易使用。它只需要一个函数来返回所需分布的对数概率。所以我定义了这个函数
这里,
C
是多元正态分布的协方差矩阵。然后,您可以运行类似于对于给定的
mean
,bounds
和C
。你需要对步行者的位置pos
进行初始猜测,这可能是平均值周围的一个球,或者从未截断的多元正态中采样,
我个人首先做了几千步的样本丢弃,因为它很快,然后迫使剩余的离群值回到边界内,然后运行MCMC采样。
收敛的步骤由您决定。
还请注意,emcee通过将参数
threads=Nthreads
添加到EnsembleSampler
初始化来轻松支持基本并行化。所以你可以速战速决。fkaflof62#
我重新实现了一个算法,它不依赖于MCMC,而是从截断的多元正态分布中创建独立同分布(iid)样本。拥有iid样本可能非常有用!我过去也使用过Warrick在回答中描述的emcee,但是为了收敛,所需的样本数量在更高的维度上爆炸,这对我的用例来说是不切实际的。
该算法由Botev (2016)引入,并使用基于极小极大指数倾斜的接受-拒绝算法。它是originally implemented in MATLAB,但与在Python中使用MATLAB引擎运行它相比,为Python重新实现它显着提高了性能。它在更高的维度上也工作得很好,速度很快。
该代码可从以下网址获得:https://github.com/brunzema/truncated-mvn-sampler。
示例:
绘制第一个尺寸将导致:
参考:
Botev,Z.I.,(2016),线性约束下的正态律:模拟和估计通过极小极大倾斜,杂志的皇家统计学会系列B,79,第1期,第。125-148
wpx232ag3#
模拟截断的多元正态可能很棘手,通常涉及MCMC的一些条件采样。
我的简短回答是,你可以使用我的代码(https://github.com/ralphma1203/trun_mvnt)!!!它实现了从x1c 0d1x开始的Gibbs采样器算法,该算法可以处理
形式的一般线性约束,即使您有非满秩D和比维数更多的约束。
t30tvxxf4#
我编写了一个脚本来测量到目前为止提供的解决方案的运行时间。要绘制50维分布的100个样本,运行时间为
1.使用emcee 217.914969 s
为了比较,使用Cholesky分解的没有任何截断的采样花费0.000201秒。
对于这个特定的场景,Botev 2016 implementation是从截断的多元正态分布中采样的最快方法。emcee方法要慢得多,但也许可以调整它以获得更好的性能。
输出是在6核x86机器上用以下代码生成的。
3pmvbmvn5#
我想有点晚了,但为了记录在案,你可以用汉密尔顿蒙特卡罗。Matlab中有一个模块叫做HMC exact。翻译成Py应该不难。