PyMC:如何定义两个随机变量的函数,没有封闭形式的分布?

机器算法验证 Python 吉布斯 pymc
2022-03-04 07:41:54

我正在学习 PyMC,基本上我有一个随机变量其中(比如说)并且 没有简单的封闭形式分布。现在我有观察 of,我想推断使用 PyMC 最直接的方法是什么?Z=X+YXNormal(θX)YLognormal(θY)Zzi,i=1...NZθXθY

如果我有可用的分布,那么我想我可以这样做:Z

Z = DistZ('Z', param_x=theta_x, param_y=theta_y, value=z, observed=True)

然后做推断,但我不知道DistZ也很容易将总和定义为:

@pymc.deterministic
def z_sum(x=Y, Y=y):
    return x + y

但是我认为我不能定义观察到的确定性函数。

我可以做类似的事情:

@pymc.stochastic(observed=True)
def z_sum(value=z, x=X, y=Y):
    def logp(z, x):
        # return log-likelihood

但我不清楚细节。我确实知道联合似然,但我希望不需要它。L(z,x)

我可以使用自定义 Gibbs 采样器(使用联合似然)来做到这一点,但我正在寻找一个更“优雅”的 PyMC 解决方案。


编辑:在错误常见问题解答中发现了一个类似的问题,说不支持随机变量的函数。不确定这是否适用于 PyMC,以及标准方法是什么。

3个回答

我会使用潜在变量方法,因为这就是 x 和 y。但是,尚不清楚在这种情况下是否可以识别所有四个参数。如果您有其中一两个的先验信息,那将很有帮助。这是一个例子:

import pymc as pm

# Priors
mu_x = pm.Normal('mu_x', 0, 0.001, value=0)
sigma_x = pm.Uniform('sigma_x', 0, 100, value=1)
tau_x = sigma_x**-2

mu_y = pm.Normal('mu_y', 0, 0.001, value=1)
sigma_y = pm.Uniform('sigma_y', 0, 100, value=1)
tau_y = sigma_y**-2

# Latent variable
y = pm.Lognormal('y', mu_y, sigma_y, size=len(z_data))

@pm.observed
def Z(value=z_data, mu=mu_x, tau=tau_x, y=y):
    # Likelihood for x (also latent, but fixed given y and z)
    return pm.normal_like(value-y, mu, tau)

我认为这里有几种方法。

第一种方法

据我所知,没有办法使用@deterministic@stochastic(没有可能性)。另一种方法是使用potentials 类,这就像将您的可能性乘以一个因子。在这种情况下,我们应该乘以给定 的对数正态分布的 pdf 。ZX

import pymc as mc

z = -1.

#instead of 0 and 1, unknowns can be put here. For example:
# mc.Normal( "x", unknown_mu, unknown_std ).

X = mc.Normal( "x", 0, 1, value = -2. ) 


@mc.potential
def Y( x =X, z = z): #similar to my comment above, you can place unknowns here in place of 1, 0.2. 
  return mc.lognormal_like( z-x, 1, 0.2,  )


mcmc = mc.MCMC( [X] )
mcmc.sample(20000,5000)

注意是负数,所以这也必须使为负数。我们观察到这一点: ZX在此处输入图像描述

通过对称性(因为的后验是相似的:Y=ZXY

在此处输入图像描述

Z 是观察向量

如果是观察向量,则势函数可以修改为:Z

z = [2,3,4]

#...
X = mc.Normal( "x", 0, 1, value = -2., size = 3 ) 

@mc.potential
def Y( x =X, Z = Z):
  return mc.lognormal_like( Z, 1, 0.2,  )

扩展到两个以上的线性组合,例如,还有待继续。Z=X1+X2+...+XN


第二种方法

一个更具体的方法是注意到由于是正常的,我们可以将此任务视为XZ=Y+noise

import pymc as mc

Z = -1

Y = mc.Lognormal( "y", 1, 0.2 )

obs = mc.Normal( "obs", 0, 1, value = Z, observed = True )


mcmc = mc.MCMC( [Y, obs] )

mcmc.sample( 20000,5000 )

运行第二个版本确实给了我一些不稳定的结果(返回了一些令人难以置信的大值)

从概念上讲,要进行贝叶斯推理,必须使用具有特定 pdf 的条件似然函数。在您的情况下,您必须提供 (X,Y) 的实际联合分布。也许潜在功能可以提供帮助,但想法是一样的,做 MCMC 的最终入口点应该是特定的日志 pdf。

如果 X 和 Y 是独立的,那么它们的 pdf 之和就是两个 pdf 的卷积。所以 Z ~ Normal(thetax)*logNormal(thetay)。也许可以评估卷积积分。