我试图将PyMC2中潜在多项式模型的this example移植到PyMC3。
目的是根据 T 观察时间的时间序列估算封闭人口中个体的实际数量 N 。
每个人都有2 ^ T个可能的系列 - 所以如果T = 2,个体可以被观察到永远不会(0,0)[让他们调用这个序列1],只有第一次(1 ,0)[序列2],仅第二次(0,1)[序列3]或两次(1,1)[序列4]。
我们知道一个人是否产生了序列2到4,所以我们有这些计数。
然而,该模型依赖于我们根据 N 的采样值来确定存在但未被观察到的个体数量(序列1)。
在原始的PyMC2模型中,只需将N - sum(f)
附加到f
的开头即可,其中f
是序列2到{2}的观察计数的np.array
2 ^ T。在PyMC3中,这必须使用Theano完成,其他一些变量也被定义为Theano共享变量。
原始PyMC2代码如下所示:
from pymc import Lambda, Beta, DiscreteUniform, stochastic, multinomial_like
from numpy import reshape, ma, prod, array, append
import pdb
# Constants
T=2
Cells=4
# Observations seen by both observers, just the first observer, or just the second
f=(22,363,174)
# Inidicators for observer sightings
omegas=reshape((0,0, 1,0, 0,1, 1,1), (Cells, T))
# Capture probabilities
p = Beta('p', alpha=1, beta=1, size=T)
# Cell probabilities
c = Lambda('c', lambda p=p: p**omegas * (1-p)**(1.-omegas))
# Joint probabilities
pi = Lambda('pi', lambda c=c: prod(c, 1))
# Bound total N by the number of observed individuals
N = DiscreteUniform('N', lower=sum(f), upper=10000)
@stochastic(observed=True, dtype=int)
def F(value=f, n=N, p=pi):
"""Complete multinomial for observed and unobserved quatities"""
return multinomial_like(append(n-sum(value), value), n, p)
我第一次尝试PyMC3版本(在Python 2.7中)看起来像这样:
from __future__ import division, absolute_import, print_function
import numpy as np
import pymc3 as pm
import theano.tensor as tt
from theano import shared
# Constants
T = 2
CELLS = 4
with pm.Model() as model_mt:
f = shared(np.array((22, 363, 174)))
omegas = shared(np.reshape((0,0, 1,0, 0,1, 1,1), (CELLS, T)))
p = pm.Beta('p', alpha=1, beta=1, shape=T)
# Treating c and pi as separate steps, as per his example:
# c = p ** omegas
# pi = tt.prod(c, axis=1)
# Shorter line of code:
pi = tt.prod(p ** omegas, axis=1)
N = pm.DiscreteUniform('N', lower=f.sum(), upper=10000)
observed_values = tt.concatenate(([N-tt.sum(f)], f))
y_obs = pm.Multinomial('y_obs', n=N, p=pi, observed=observed_values)
with model_mt:
trace = pm.sample(5000)
但由此产生的痕迹看起来难以置信。 p_0
的平均值为0.27,p_1
的平均值为0.98,我理解为在t = 1和t = 2时看到个体的值({{1} }的平均值为930.但不应该N
接近p_1
吗?
答案 0 :(得分:4)
以下是我将此模型转换为PyMC3的方法(我一直有意这样做,谢谢):
with pm.Model() as Mt2:
p = pm.Uniform('p', 0, 1, shape=T)
c = p**omega * (1 - p)**(1-omega)
π = pm.Deterministic('π', tt.prod(c, 1))
π_obs = π[1:] / (1 - π[0])
f_obs = pm.Potential('f_obs', pm.Multinomial.dist(n=n, p=π_obs).logp(f[1:]))
N = pm.Uniform('N', 0, 10000)
n_obs = pm.Potential('n_obs', pm.Binomial.dist(n=tt.floor(N), p=1-π[0]).logp(n))
trace = pm.sample(1000, tune=1000)
将N
保持为连续变量并对部分观察到的可观察量使用因子势允许PyMC3使用NUTS而不是回退到Metropolis。
我不记得这与PyMC2(或Link和Barker)输出相比如何,但它远远低于你的估计值。
以下是我对捕获概率的估计:
p[0]
的估计值为0.325(0.290,0.367),p[1]
的估计值为0.894(0.853,0.936)。