在PyMC中使用自定义先验
假设我想在PyMC中给两个变量a
和b
设置一个自定义的先验,比如:
p(a,b)∝(a+b)^(−5/2)
(关于这个先验选择的原因,可以参考这个回答)
在PyMC中可以做到吗?如果可以,怎么做呢?
举个例子,我想在下面的模型中对a
和b
定义这样的先验。
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),但我有几个问题:
- 我应该导入什么,以便能够正确继承
Continuous
? - 在PyMC2中,我还需要遵循Theano的写法吗?
最后,我怎么能告诉我的
Beta
分布,alpha
和beta
是来自这个多变量分布的先验呢?import pymc.Multivariate.Continuous
class CustomPrior(Continuous):
"""
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)
2 个回答
4
没错!这完全是可能的,而且其实也很简单。
如果你在用PyMC 2,可以看看关于创建随机变量的文档。
@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)))