【问题标题】:MCMC Sampling a Maxwellian Curve Using Python's emceeMCMC 使用 Python 的 emcee 对麦克斯韦曲线进行采样
【发布时间】:2017-05-14 13:56:11
【问题描述】:

我正在尝试通过主持人介绍自己参加 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)

谢谢

【问题讨论】:

  • 在 SO 上,我们更愿意查看 您的 代码,以便我们确切知道我们面临的问题。
  • 当然,对不起!我现在已经添加了。
  • 不用担心。如果我每次写那篇文章都能得到一分钱……
  • 当我运行这段代码时,我得到了完全不同的(邪恶的)结果:一系列溢出警告,然后是与 NaN 相关的值错误。我在 Windows10 上运行 Py3.4。
  • 嗨,比尔,我在 Windows 10 上运行 Py2.7。我现在似乎也遇到了同样的错误。我对函数如何返回 Nan 感到迷茫?当我使用 scipy 定义分布时,也会出现相同的响应

标签: python probability mcmc emcee


【解决方案1】:

我认为我看到了几个问题。主要是 emcee 要你给它你要采样的概率分布函数的自然对数。所以,与其拥有:

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))

【讨论】:

    猜你喜欢
    • 2020-11-27
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 2017-04-10
    • 2020-08-26
    • 2015-10-01
    • 2015-02-21
    • 1970-01-01
    相关资源
    最近更新 更多