PyMC3通过随时间变化的捕获概率估计封闭种群的大小

时间:2017-09-19 15:01:10

标签: python numpy theano bayesian pymc3

我试图将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中的原始示例

原始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版本

我第一次尝试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吗?

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。

我估计N的估计值超过611: posterior plot of N

我不记得这与PyMC2(或Link和Barker)输出相比如何,但它远远低于你的估计值。

以下是我对捕获概率的估计:

enter image description here

p[0]的估计值为0.325(0.290,0.367),p[1]的估计值为0.894(0.853,0.936)。