我对PyMC很陌生,我正在拼命地推断出最符合我所观察到的数据分布的基础高斯分布的参数,而不是预先构建的正常分布,而是更多使用模拟数据的直方图来构建pdf的一般方法。但到目前为止,我无法让我的代码收敛,我不知道为什么......
所以这里是我的代码所做的总结。
我有一个正常分布的5000点数据集(平均值= 5,sigma = 2)。我想用贝叶斯推理(使用MCMC)检索这些值(mean,sigma)。
我有一个数据模拟器,它为MCMC过程的每次迭代生成5000个点的正态分布,具有随机均值和sigma(统一先验) 从模拟的点分布,我计算出一个numpy直方图,其标准为1表示分布的pdf(Nbins = int(sqrt(5000)))。然后我计算这个分布的均值和标准差。 我想要的是一组参数,这些参数可以让我建立一个最适合观察数据的模拟分布。
我使用对数似然的最一般定义,即:
ln L(θ| x)=Σln(f(xi |θ))(似然函数被定义为给定参数θ的观测数据的概率分布)
然后我线性地插入每个bin中心的直方图值。因此,我有一个连续的pdf模拟分布。所以这里f是我从模拟的直方图中得到的插值函数。 我对每个(实际)数据点的log(f(xi))贡献求和,并在结束时返回loglikelihood值。
但是一些(实际)数据点与f(xi)= 0的模拟分布的平均值相差甚远。对于这些点,代码会引发数学域错误(提醒:log(0)= - inf)。所以我人为地将pdf设置为一个小epsilon,用于通常设置为0的点。
但是这就是事情。每次迭代都不计算对数似然。实际上,在我的代码的当前架构中,它根本没有计算。这就是MCMC流程不融合的原因。但是......我不知道为什么。
事实证明,在PyMC社区中构建自定义似然函数似乎不是非常随意的方法,人们通常更喜欢使用预构建的发行版。我在找到这方面的帮助方面遇到了麻烦,因此我们将非常感谢您的想法和建议:)
import numpy as np
import matplotlib.pyplot as plt
import math
import pymc as pm
from scipy.interpolate import InterpolatedUnivariateSpline
# Generate the data
np.random.seed(0)
N=5000
true_mean=5.
true_sigma = 2.
data = np.random.normal(true_mean,true_sigma,N)
#prior
m=pm.Uniform('m', lower=4, upper=6)
s=pm.Uniform('s', lower=1, upper=3)
@pm.deterministic
def data_simulator(mean_input=m,sig_input=s):
out=np.empty(4,dtype=object)
datasim = np.random.normal(mean_input,sig_input,N)
hist, bin_edges = np.histogram(datasim, bins=int(math.sqrt(len(datasim))), density=True)
bin_centers = (bin_edges[:-1] + bin_edges[1:])/2
m_sim=np.mean(datasim)
s_sim=np.std(datasim)
out[0]=m_sim
out[1]=s_sim
out[2]=bin_centers
out[3]=hist
return out
@pm.stochastic(observed=True)
def logp(value=data,mean_output=data_simulator.value[0],sigma_output=data_simulator.value[1],bin_centers_sim=data_simulator.value[2],hist_sim=data_simulator.value[3]):
interp_sim=InterpolatedUnivariateSpline(bin_centers_sim,hist_sim,k=1,ext=0) #returns the extrapolated values
logp=np.sum(np.log(interp_sim(value)))
print 'logp=',logp
return logp
model = pm.Model({"mean": m,"sigma":s,"data_simulator":data_simulator,"loglikelihood":loglikelihood})
#Run the MCMC sampler
mcmc = pm.MCMC(model)
mcmc.sample(iter=10000, burn=5000)
#Plot the marginals
pm.Matplot.plot(mcmc)