当参数已知时,如何从自定义分布中采样?

时间:2019-07-01 15:50:57

标签: python bayesian pymc3 mcmc

目标是从已知参数的分布中获取样本。

例如,自定义分布为p(X | theta),其中theta为K维的参数矢量,X为N维的随机矢量。

现在我们知道(1)theta是已知的; (2)p(X | theta)未知,但我知道p(X | theta)∝ f(X,theta),f是已知函数。

pymc3可以从p(X | theta)进行这种采样吗?

目的不是从参数的后验分布中采样,而是要从自定义分布中采样。

从一个简单的伯努利分布抽样示例开始。我做了以下事情:

import pymc3 as pm
import numpy as np
import scipy.stats as stats
import pandas as pd
import theano.tensor as tt

with pm.Model() as model1:
    p=0.3
    density = pm.DensityDist('density',
                             lambda x1: tt.switch( x1, tt.log(p), tt.log(1 - p) ),
                             ) #tt.switch( x1, tt.log(p), tt.log(1 - p) ) is the log likelihood from pymc3 source code

with model1:
    step = pm.Metropolis()
    samples = pm.sample(1000, step=step)

我希望结果是1000个二进制数字,其中1的比例约为0.3。但是,在输出中出现大量数字的情况下,我得到了奇怪的结果。

我知道出了点问题。请为如何正确地为此类非后置MCMC采样问题编写pymc3代码提供帮助。

1 个答案:

答案 0 :(得分:1)

先前的预测采样(您应该使用pm.sample_prior_predictive())仅涉及使用计算图中RandomVariable对象提供的RNG。默认情况下,DensityDist不实现RNG,但是为此目的提供了random参数,因此您需要使用它。对数似然率仅针对可观察对象进行评估,因此在这里不起作用。

为任意分布生成有效RNG的一种简单方法是使用inverse transform sampling。在这种情况下,可以对单位间隔上的均匀分布进行采样,然后通过所需函数的逆CDF对其进行变换。对于伯努利情况,逆CDF根据成功概率对单位线进行划分,将0分配给一个零件,将1分配给另一零件。

这是一种类似于工厂的实现,它创建与pm.DensityDist的{​​{1}}参数兼容的Bernoulli RNG(即,接受randompoint kwarg)。

size

因此,要填写示例,它将类似于

def get_bernoulli_rng(p=0.5):

    def _rng(point=None, size=1):
        # Bernoulli inverse CDF, given p (prob of success)
        _icdf = lambda q: np.uint8(q < p)

        return _icdf(pm.Uniform.dist().random(point=point, size=size))

    return _rng

很显然,这可以同样地用with pm.Model() as m: p = 0.3 y = pm.DensityDist('y', lambda x: tt.switch(x, tt.log(p), tt.log(1-p)), random=get_bernoulli_rng(p)) prior = pm.sample_prior_predictive(random_seed=2019) prior['y'].mean() # 0.306 完成,但是上面给出了一个通用的例子,给出了逆CDF,即只要修改random=pm.Bernoulli.dist(p).random且参数。