过去几天我一直在努力习惯PyMC最终从我直接编码的一些模型中做一些MCMC的分布抽样(我最终对参数估计感兴趣)。
据我所知,没有那么多人展示他们的代码(如外部C或FORTRAN代码),他们成功地使用PyMC3。到目前为止,我发现了here或here信息贿赂。
因此,从简单的问题开始,我尝试用PyMC3重现现有Python代码的一些结果,这些代码使用'复杂'(读取:比文档示例更多)不使用PyMC的分布来执行MCMC,即这个简单的result我的笔记本电脑上的10000个样本在2秒内运行。
要在PyMC3中定义确定性变量,应该使用@theano.compile.ops.as_op装饰器(在PyMC中它是@deterministic,现在在PyMC3中已弃用),这就是我所做的。
这是我的代码(我使用Spyder和IPython),受到PyMC documentation的启发,我在第二个单元格之后遇到AssertionError
(在估算过程中,所以在采样之前)。
我过去两天一直试图解决这个问题,但我真的不明白错误是什么。我相信它应该是某种PyMC或Theano技巧,我还没有抓到,因为我相信我真的很接近。
#%% Define model
import numpy,math
import matplotlib.pyplot as plt
import random as random
import theano.tensor as t
import theano
random.seed(1) # set random seed
# copy-pasted function from the specific model used in the source and adapted with as_op
@theano.compile.ops.as_op(itypes=[t.iscalar, t.dscalar, t.fscalar, t.fscalar],otypes=[t.dvector])
def sampleFromSalpeter(N, alpha, M_min, M_max):
log_M_Min = math.log(M_min)
log_M_Max = math.log(M_max)
maxlik = math.pow(M_min, 1.0 - alpha)
Masses = []
while (len(Masses) < N):
logM = random.uniform(log_M_Min,log_M_Max)
M = math.exp(logM)
likelihood = math.pow(M, 1.0 - alpha)
u = random.uniform(0.0,maxlik)
if (u < likelihood):
Masses.append(M)
return Masses
# SAME function as above, used to make test data (so no Theano here)
def sampleFromSalpeterDATA(N, alpha, M_min, M_max):
log_M_Min = math.log(M_min)
log_M_Max = math.log(M_max)
maxlik = math.pow(M_min, 1.0 - alpha)
Masses = []
while (len(Masses) < N):
logM = random.uniform(log_M_Min,log_M_Max)
M = math.exp(logM)
likelihood = math.pow(M, 1.0 - alpha)
u = random.uniform(0.0,maxlik)
if (u < likelihood):
Masses.append(M)
return Masses
# Generate toy data.
N = 1000000 # Draw 1 Million stellar masses.
alpha = 2.35
M_min = 1.0
M_max = 100.0
Masses = sampleFromSalpeterDATA(N, alpha, M_min, M_max)
#%% Estimation process
import pymc3 as pm
basic_model = pm.Model()
with basic_model:
# Priors for unknown model parameters
alpha2 = pm.Normal('alpha2', mu=3, sd=10)
N2=t.constant(1000000)
M_min2 = t.constant(1.0)
M_max2 = t.constant(100.0)
# Expected value of outcome
m = sampleFromSalpeter(N2, alpha2, M_min2, M_max2)
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=m, sd=10, observed=Masses)
#%% Sample
with basic_model:
step = pm.Metropolis()
trace = pm.sample(10000, step=step)
#%% Plot posteriors
_ = pm.traceplot(trace)
pm.summary(trace)
答案 0 :(得分:0)
我在Discourse of PyMC得到了答案。我确实非常接近,因为我只需要更改函数定义的最后一行以返回[numpy.array(Masses)]。
现在,似乎这段代码需要大约300小时才能运行(而不是没有PyMC的原始实现中的2秒),我想知道是否有人知道它为什么这么慢? 我实际上早先尝试过非常简单的发行版并使用as_op,并注意到一个相当大的减速但是甚至没有这么多。 我猜原始代码直接在logp上运行,是不是它有什么区别呢?