我试图用emcee向MCMC采样介绍自己。我想简单地使用github上的一组示例代码https://github.com/dfm/emcee/blob/master/examples/quickstart.py从Maxwell Boltzmann分布中获取样本。
示例代码非常出色,但是当我将分布从高斯分布更改为麦克斯韦分布时,我收到错误, TypeError:lnprob()正好接受2个参数(给定3个)
然而,如果没有给出适当的参数,它就不会被调用?需要一些关于如何定义麦克斯韦曲线并使其适合此示例代码的指导。
这就是我所拥有的;
from __future__ import print_function
import numpy as np
import emcee
try:
xrange
except NameError:
xrange = range
def lnprob(x, a, icov):
pi = np.pi
return np.sqrt(2/pi)*x**2*np.exp(-x**2/(2.*a**2))/a**3
ndim = 2
means = np.random.rand(ndim)
cov = 0.5-np.random.rand(ndim**2).reshape((ndim, ndim))
cov = np.triu(cov)
cov += cov.T - np.diag(cov.diagonal())
cov = np.dot(cov,cov)
icov = np.linalg.inv(cov)
nwalkers = 50
p0 = [np.random.rand(ndim) for i in xrange(nwalkers)]
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, args=[means, icov])
pos, prob, state = sampler.run_mcmc(p0, 5000)
sampler.reset()
sampler.run_mcmc(pos, 100000, rstate0=state)
由于
答案 0 :(得分:1)
我认为我看到了一些问题。主要的一点是,主持人希望你给它想要抽样的概率分布函数的自然对数。所以,而不是:
def lnprob(x, a, icov):
pi = np.pi
return np.sqrt(2/pi)*x**2*np.exp(-x**2/(2.*a**2))/a**3
你会反而想要,例如
def lnprob(x, a):
pi = np.pi
if x < 0:
return -np.inf
else:
return 0.5*np.log(2./pi) + 2.*np.log(x) - (x**2/(2.*a**2)) - 3.*np.log(a)
其中if ... else ...语句明确表示x
的负值具有零概率(或对数空间中的-infinity)。
您也不必计算icov
并将其传递给lnprob
,因为在您链接的示例中,仅需要高斯案例。
致电时:
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, args=[means, icov])
args
值应该是您的lnprob
函数所需的任何其他参数,因此在您的情况下,这将是您想要设置Maxwell-Boltxmann的a
的值分发。这应该是单个值,而不是您在创建mean
时设置的两个随机初始值。
总的来说,以下内容适用于您:
from __future__ import print_function
import emcee
import numpy as np
from numpy import pi as pi
# define the natural log of the Maxwell-Boltzmann distribution
def lnprob(x, a):
if x < 0:
return -np.inf
else:
return 0.5*np.log(2./pi) + 2.*np.log(x) - (x**2/(2.*a**2)) - 3.*np.log(a)
# choose a value of 'a' for the distributions
a = 5. # I'm choosing 5!
# choose the number of walkers
nwalkers = 50
# set some initial points at which to calculate the lnprob
p0 = [np.random.rand(1) for i in xrange(nwalkers)]
# initialise the sampler
sampler = emcee.EnsembleSampler(nwalkers, 1, lnprob, args=[a])
# Run 5000 steps as a burn-in.
pos, prob, state = sampler.run_mcmc(p0, 5000)
# Reset the chain to remove the burn-in samples.
sampler.reset()
# Starting from the final position in the burn-in chain, sample for 100000 steps.
sampler.run_mcmc(pos, 100000, rstate0=state)
# lets check the samples look right
mbmean = 2.*a*np.sqrt(2./pi) # mean of Maxwell-Boltzmann distribution
print("Sample mean = {}, analytical mean = {}".format(np.mean(sampler.flatchain[:,0]), mbmean))
mbstd = np.sqrt(a**2*(3*np.pi-8.)/np.pi) # std. dev. of M-B distribution
print("Sample standard deviation = {}, analytical = {}".format(np.std(sampler.flatchain[:,0]), mbstd))