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

How to sample from a custom distribution when parameters are known?

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

比如自定义分布为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 代码。

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

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

这是一个 factory-like 实现,它创建了一个与 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和参数。