入门简单的pymc3示例很麻烦

时间:2018-11-16 17:50:43

标签: python r bayesian pymc3 jags

我对使用PyMC3软件包是陌生的,我只是尝试从我所采取的有关测量不确定性的课程中实施一个示例。 (请注意,这是一门可选的通过工作进行的员工教育课程,而不是我不应该在线找到答案的分级课程)。该课程使用R,但我认为python更可取。

(简单)问题提出如下:

假设您有一个在室温length下的实际(未知)长度和测得的长度m的量规。两者之间的关系是:

length = m / (1 + alpha*dT)

其中alpha是膨胀系数,dT是与室温的偏差,m是测量量。目的是找到length上的后验分布,以确定其期望值和标准偏差(即测量不确定度)

问题指定了alpha和dT的先验分布(标准偏差小的高斯),而length上的先验分布(标准偏差大的高斯)。该问题表明m被测量了25次,平均值为50.000215,标准偏差为5.8e-6。我们假设m的测量值的正态分布是m的真实值的平均值。

我遇到的一个问题是,似乎不能仅根据PyMC3中的这些统计数据来指定可能性,所以我生成了一些虚拟的测量数据(我最终进行了1000次测量,而不是25次)。再次,问题是要在length上进行后验分布(在此过程中,尽管兴趣不大,但要在alphadT上更新后验。)

这是我的代码,该代码不起作用并且存在收敛问题:

from IPython.core.pylabtools import figsize
import numpy as np
from matplotlib import pyplot as plt
import scipy.stats as stats
import pymc3 as pm
import theano.tensor as tt

basic_model = pm.Model()

xdata = np.random.normal(50.000215,5.8e-6*np.sqrt(1000),1000)

with basic_model:
    #prior distributions
    theta = pm.Normal('theta',mu=-.1,sd=.04)
    alpha = pm.Normal('alpha',mu=.0000115,sd=.0000012)
    length = pm.Normal('length',mu=50,sd=1)

mumeas = length*(1+alpha*theta)


with basic_model:
    obs = pm.Normal('obs',mu=mumeas,sd=5.8e-6,observed=xdata)
    #yobs = Normal('yobs',)
    start = pm.find_MAP()
    #trace = pm.sample(2000, step=pm.Metropolis, start=start)
    step = pm.Metropolis()
    trace = pm.sample(10000, tune=200000,step=step,start=start,njobs=1)


length_samples = trace['length']

fig,ax=plt.subplots()
plt.hist(length_samples, histtype='stepfilled', bins=30, alpha=0.85,
     label="posterior of $\lambda_1$", color="#A60628", normed=True)

我真的很感谢任何关于为什么它不起作用的帮助。我已经尝试了一段时间,它从未收敛到R代码给出的预期解决方案。我尝试了默认采样器(我认为是NUTS)以及Metropolis,但由于零梯度误差而完全失败。 (相关的)课程幻灯片以图像形式附加。最后,这是类似的R代码:

library(rjags)

#Data
jags_data <- list(xbar=50.000215) 

jags_code <- jags.model(file = "calibration.txt",
                    data = jags_data, 
                    n.chains = 1, 
                    n.adapt = 30000)


post_samples <- coda.samples(model = jags_code, 
                         variable.names = 
c("l","mu","alpha","theta"),#,"ypred"),
                         n.iter = 30000)


summary(post_samples)

mean(post_samples[[1]][,"l"])
sd(post_samples[[1]][,"l"])

plot(post_samples)

和Calibration.txt模型:

model{
  l~dnorm(50,1.0)
  alpha~dnorm(0.0000115,694444444444)
  theta~dnorm(-0.1,625)
  mu<-l*(1+alpha*theta)
  xbar~dnorm(mu,29726516052)
}

(请注意,我认为dnorm分布采用1 / sigma ^ 2,因此看起来很奇怪)

enter image description here

任何有关PyMC3采样为何不收敛以及我应该做些不同的事情的帮助或见解,将非常感谢。谢谢!

1 个答案:

答案 0 :(得分:1)

我也很难从代码中的生成数据和模型中获得任何有用的信息。在我看来,假数据中的噪声水平同样可以由模型中不同的方差源来解释。这可能导致后参数高度相关的情况。再加上极端的规模失衡,那么这就会带来抽样问题。

但是,看一下JAGS模型,似乎他们确实只是在使用一个输入观察。我以前从未见过这种技术(?),即输入数据的摘要统计信息而不是原始数据本身。我想它在JAGS中对他们有用,所以我决定尝试运行完全相同的MCMC,包括使用高斯精确(tau)参数化。

大都会的原始模型

with pm.Model() as m0:
    # tau === precision parameterization
    dT = pm.Normal('dT', mu=-0.1, tau=625)
    alpha = pm.Normal('alpha', mu=0.0000115, tau=694444444444)
    length = pm.Normal('length', mu=50.0, tau=1.0)

    mu = pm.Deterministic('mu', length*(1+alpha*dT))

    # only one input observation; tau indicates the 5.8 nm sd
    obs = pm.Normal('obs', mu=mu, tau=29726516052, observed=[50.000215])

    trace = pm.sample(30000, tune=30000, chains=4, cores=4, step=pm.Metropolis())

虽然在采样lengthdT方面还不够出色,但总体看来至少是收敛的:

enter image description here

我认为这里值得注意的是,尽管lengthsd=1)的先验相对较弱,但所有其他参数上的强先验似乎会传播length上的严格不确定性后部。归根结底,这是令人感兴趣的后验,因此这似乎与练习的意图是一致的。另外,请注意,mu恰好在所描述的分布N(50.000215, 5.8e-6)的后面出现。

痕迹图

enter image description here

森林图

enter image description here

对图

但是,您可以在此处看到核心问题仍然存在。 lengthdT之间都具有很强的相关性,加上标准误差之间的4或5个数量级的尺度差异。我肯定会花很长时间才能真正相信结果。

enter image description here

使用NUTS的替代模型

为了使它与NUTS一起运行,您必须解决扩展问题。也就是说,我们需要以某种方式重新设置参数,以使所有tau值更接近1。然后,您将运行采样器并将其转换回您感兴趣的单位。不幸的是,我没有时间立即尝试(我也必须弄清楚),但这也许是您可以自己开始探索的东西。