【问题标题】:Custom priors in PyMCPyMC 中的自定义先验
【发布时间】:2014-04-21 13:18:03
【问题描述】:

假设我想在 PyMC 中对两个变量 ab 进行自定义先验,例如:

p(a,b)∝(a+b)^(−5/2)

(关于这种先验选择背后的动机,请参阅this answer

这可以在 PyMC 中完成吗?如果有怎么办?

例如,我想在下面的模型中定义 ab 这样的先验。

import pymc as pm

# ...
# Code that defines the prior: p(a,b)∝(a+b)^(−5/2)
# ...

theta   = pm.Beta("prior", alpha=a, beta=b)

# Binomials that share a common prior
bins = dict()
for i in xrange(N_cities):
    bins[i] = pm.Binomial('bin_{}'.format(i), p=theta,n=N_trials[i],  value=N_yes[i], observed=True)

mcmc = pm.MCMC([bins, ps])

更新

按照 John Salvatier 的建议,我尝试了以下方法(请注意,我在 PyMC2 中,虽然我很乐意切换到 PyMC3),但我的问题是:

  1. 我应该导入什么才能正确继承Continuous
  2. 在 PyMC2 中,我还需要坚持 Theano 表示法吗?
  3. 最后,我以后如何告诉我的 Beta 分布 alphabeta 具有来自此多元分布的先验?

    导入 pymc.Multivariate.Continuous

    类 CustomPrior(连续): """ p(a,b)∝(a+b)^(−5/2)

    :Parameters:
        None
    
    :Support:
        2 positive floats (parameters to a Beta distribution)
    """
    def __init__(self, mu, tau, *args, **kwargs):
        super(CustomPrior, self).__init__(*args, **kwargs)
    
    def logp(self, a,b):
    
    
        return np.log(math.power(a+b),-5./2)
    

【问题讨论】:

  • 哦,对不起,我以为你出于某种原因在 PyMC3 中。您可以在 pymc2 中执行此操作,但它不同。我会更新我的答案

标签: python statsmodels pymc


【解决方案1】:

是的!这是很有可能的,实际上也很简单。

如果您使用 PyMC 2,请查看documentation on the creation of stochastic variables

@pymc.stochastic(dtype=int)
def switchpoint(value=1900, t_l=1851, t_h=1962):
    """The switchpoint for the rate of disaster occurrence."""
    if value > t_h or value < t_l:
        # Invalid values
        return -np.inf
    else:
        # Uniform log-likelihood
        return -np.log(t_h - t_l + 1)

如果您使用的是 PyMC 3,请查看 multivariate.py。请记住,传入 init 和 logp 的值都是 theano 变量,而不是 numpy 数组。这足以让您入门吗?

例如,这是多元正态分布

class MvNormal(Continuous):
    """
    Multivariate normal

    :Parameters:
        mu : vector of means
        tau : precision matrix

    .. math::
        f(x \mid \pi, T) = \frac{|T|^{1/2}}{(2\pi)^{1/2}} \exp\left\{ -\frac{1}{2} (x-\mu)^{\prime}T(x-\mu) \right\}

    :Support:
        2 array of floats
    """
    def __init__(self, mu, tau, *args, **kwargs):
        super(MvNormal, self).__init__(*args, **kwargs)
        self.mean = self.median = self.mode = self.mu = mu
        self.tau = tau

    def logp(self, value):
        mu = self.mu
        tau = self.tau

        delta = value - mu
        k = tau.shape[0]

        return 1/2. * (-k * log(2*pi) + log(det(tau)) - dot(delta.T, dot(tau, delta)))

【讨论】:

  • 非常感谢@John。我想我理解上面的定义,但我试图遵循这些步骤但没有成功。我已经用更具体的问题更新了 OP。
  • 谢谢@John。这很有帮助。剩下的唯一问题是我如何使用多变量先验来获得各个变量的先验(例如,二项分布中的alphabeta,如OP 中的代码所示)。如何从多元先验中获得单个变量的先验?
  • 哦,你想对不同名称的变量进行多元先验吗?我不认为有办法做到这一点。您可以创建一个多元变量并对其进行索引以分别获取组件,然后为它们命名。这就是你想要的吗?
  • 谢谢@John。在我的 OP 顶部的代码示例中,我定义了 theta = pm.Beta("prior", alpha=a, beta=b)。我想要做的是将ab 上的先前定义为p(a,b)∝(a+b)^(−5/2)。看起来我可以在 PyMC2 中用@pymc.stochastic 定义p(a,b),正如您在回答中提到的那样。我以后需要将ab 传递给上面的Beta 调用。这是我不知道该怎么做的部分。
【解决方案2】:

在 PyMC2 中,诀窍是将 ab 参数放在一起:

# Code that defines the prior: p(a,b)∝(a+b)^(−5/2)
@pm.stochastic
def ab(power=-2.5, value=[1,1]):
    if np.any(value <= 0):
        return -np.Inf
    return power * np.log(value[0]+value[1])

a = ab[0]
b = ab[1]

This notebook 有一个完整的例子。

【讨论】:

  • 谢谢!这正是我想要的正是。我一直在寻找这个问题的答案很长一段时间。顺便说一下,你知道如何在 PyMC3 中做到这一点吗?
  • 不客气。我已经通过错误修复(返回日志概率)和 PyMC3 版本的开头更新了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 2013-05-19
  • 2013-11-03
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多