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



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

例如,自定义的分布是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个二进制数字,其比例约为0.3。但是,在输出中发生很大数字的情况下,我得到了奇怪的结果。

我知道有什么问题。请帮助如何正确编写此类非正式MCMC采样问题的PYMC3代码。

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

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

这是一种类似于工厂的实现,它可以与pm.DensityDistrandom参数兼容Bernoulli RNG(即接受pointsize Kwargs(。

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

显然,这可以同样可以使用random=pm.Bernoulli.dist(p).random来完成,但是上面的说明了一个人可以使用任意分布的方式来做到这一点,因为它们的逆CDF,即,您只需要修改_icdf和参数。

最新更新