我想在pymc3模型中使用由参数loc
移动的二项分布(如scipy
)。
例如:
with pm.Model() as m1:
prob = pm.Beta('prob',alpha=2,beta=2)
x = pm.Binomial('x',n=20,p=prob,loc=5)
但是Binomial
不允许使用shift参数。
我尝试按照pymc3网站上的各种教程自己构建它,但没有成功(我是使用pymc3和theano的初学者)。我最近的尝试(可能非常糟糕)
...
from scipy.stats import binom
class BinoShift(pm.Discrete):
def __init__(self, n, p, x, *args, **kwargs):
super(BinoShift, self).__init__(*args, **kwargs)
self.n = n
self.p = p
self.mode = np.round(n*p)
self.shift = x
def logp(self, value):
n = self.n
p = self.p
shift = self.shift
return binom.logpmf(value,n,p,loc=shift)
背景:我观察到随机变量X = X_0 + z
,其中z
是未观察到的潜在变量,X_0
是未观察到的,并且与({{1 }}},已知N-z,p
。最终目标是在N
和p
上获得后验分布。这几乎与带有未观察到的群集分配的混合模型问题相对应。 z
。因此,如果我的二项式分布具有shift参数,那么我构想的pymc3模型看起来就像
X \sim \sum_z p(z)(z + Bino(p,N-z))
我尝试将这个问题构建到pymc3模型中的其他方法包括一个层次模型,最后一行引用给定其他参数/未知数的# generate data; kept simple here, but N and z may actually differ across sample
size = 500
N = 20
p = 0.7
z = 5
X = np.random.binomial(N-z,p,size=size) + z
with pm.Model() as mixture:
prob = pm.Beta('prob',alpha=2,beta=2)
weight = pm.Dirichlet('weight',a=np.array([1]*N))
comp = [pm.Binomial('X_{}'.format(i),n=N-i,p=prob,loc=i) for i in range(N)]
like = pm.Mixture('like',w=weight,comp_dists=comp,observed=X)
的分布,这就是二项分布。但是,我不愿将X-z作为“观察”值传递。我想到的另一种方法是先定义X_0
和z
的分布,然后对X_0
使用pm.Deterministic
。但是确定性类不接受观察值(我想是因为它不知道如何评估可能性)。
答案 0 :(得分:1)
pymc3复制粘贴了源代码,并添加了loc参数(已标记更改):
import numpy as np
import theano.tensor as tt
from pymc3.distributions.dist_math import bound, binomln, logpow
from pymc3.math import tround
from pymc3.theanof import floatX, intX
from pymc3.distributions.distribution import Discrete
class BinoShift(Discrete):
def __init__(self, n, p, loc, *args, **kwargs): # <---
super().__init__(*args, **kwargs)
self.n = n = tt.as_tensor_variable(intX(n))
self.loc = loc = tt.as_tensor_variable(intX(loc)) # <---
self.p = p = tt.as_tensor_variable(floatX(p))
self.mode = tt.cast(tround(n * p), self.dtype)
def logp(self, value):
n = self.n
p = self.p
loc = self.loc # <---
k = value-loc # <---
return bound(
binomln(n, k) + logpow(p, k) + logpow(1 - p, n - k),
0 <= k, k <= n,
0 <= p, p <= 1) # <---