我对使用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
上进行后验分布(在此过程中,尽管兴趣不大,但要在alpha
和dT
上更新后验。)
这是我的代码,该代码不起作用并且存在收敛问题:
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,因此看起来很奇怪)
任何有关PyMC3采样为何不收敛以及我应该做些不同的事情的帮助或见解,将非常感谢。谢谢!
答案 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())
虽然在采样length
和dT
方面还不够出色,但总体看来至少是收敛的:
我认为这里值得注意的是,尽管length
(sd=1
)的先验相对较弱,但所有其他参数上的强先验似乎会传播length
上的严格不确定性后部。归根结底,这是令人感兴趣的后验,因此这似乎与练习的意图是一致的。另外,请注意,mu
恰好在所描述的分布N(50.000215, 5.8e-6)
的后面出现。
但是,您可以在此处看到核心问题仍然存在。 length
和dT
之间都具有很强的相关性,加上标准误差之间的4或5个数量级的尺度差异。我肯定会花很长时间才能真正相信结果。
为了使它与NUTS一起运行,您必须解决扩展问题。也就是说,我们需要以某种方式重新设置参数,以使所有tau
值更接近1。然后,您将运行采样器并将其转换回您感兴趣的单位。不幸的是,我没有时间立即尝试(我也必须弄清楚),但这也许是您可以自己开始探索的东西。