目标是从已知参数的分布中获取样品。
例如,自定义的分布是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.DensityDist
的random
参数兼容Bernoulli RNG(即接受point
和size
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
和参数。