我试图玩贝叶斯更新,并且在某种情况下,我使用之前运行的后验作为先验。这是alpha
和beta
上的2D优先,我有跟踪alphatrace
和betatrace
。所以我将它们堆叠起来并使用从https://gist.github.com/jcrudy/5911624采用的代码来创建基于KDE的随机数。
#from https://gist.github.com/jcrudy/5911624
def KernelSmoothing(name, dataset, bw_method=None, observed=False, value=None):
'''Create a pymc node whose distribution comes from a kernel smoothing density estimate.'''
density = gaussian_kde(dataset, bw_method)
def logp(value):
#print "VAL", value
d = density(value)
if d == 0.0:
return float('-inf')
return np.log(d)
def random():
result = None
sample=density.resample(1)
#print sample, sample.shape
result = sample[0][0],sample[1][0]
return result
if value == None:
value = random()
dtype = type(value)
result = pymc.Stochastic(logp = logp,
doc = 'A kernel smoothing density node.',
name = name,
parents = {},
random = random,
trace = True,
value = None,
dtype = dtype,
observed = observed,
cache_depth = 2,
plot = True,
verbose = 0)
return result
请注意,这里的关键是从关节前获得2个值:这就是为什么我需要2-D先验而不是2个1-D先验。
模型本身就是这样:
ctrace=np.vstack((alphatrace, betatrace))
cnew=KernelSmoothing("cnew", ctrace)
@pymc.deterministic
def alphanew(cnew=cnew, name='alphanew'):
return cnew[0]
@pymc.deterministic
def betanew(cnew=cnew, name='betanew'):
return cnew[1]
newtheta=pymc.Beta("newtheta", alphanew, betanew)
newexp = pymc.Binomial('newexp', n=[14], p=[newtheta], value=[4], observed=True)
model3=pymc.Model([cnew, alphanew, betanew, newtheta, newexp])
mcmc3=pymc.MCMC(model3)
mcmc3.sample(20000,5000,5)
如果您想知道,这是在Gelman的BDA第5章的分层Rat Tumor例子中进行的第71次实验。 "先前"我使用的是70次实验后的α和β后验。
但是,当我抽样时,事情会因错误而爆炸:
ValueError: Maximum competence reported for stochastic cnew is <= 0... you may need to write a custom step method class.
它不是cnew
我关心的是随机更新,而是alphanew
和betanew
。我应该如何构建代码以使此错误消失?
编辑:初始模型,它给了我希望用作前面的后代:
tumordata="""0 20
0 20
0 20
0 20
0 20
0 20
0 20
0 19
0 19
0 19
0 19
0 18
0 18
0 17
1 20
1 20
1 20
1 20
1 19
1 19
1 18
1 18
3 27
2 25
2 24
2 23
2 20
2 20
2 20
2 20
2 20
2 20
1 10
5 49
2 19
5 46
2 17
7 49
7 47
3 20
3 20
2 13
9 48
10 50
4 20
4 20
4 20
4 20
4 20
4 20
4 20
10 48
4 19
4 19
4 19
5 22
11 46
12 49
5 20
5 20
6 23
5 19
6 22
6 20
6 20
6 20
16 52
15 46
15 47
9 24
"""
tumortuples=[e.strip().split() for e in tumordata.split("\n")]
tumory=np.array([np.int(e[0].strip()) for e in tumortuples if len(e) > 0])
tumorn=np.array([np.int(e[1].strip()) for e in tumortuples if len(e) > 0])
N = tumorn.shape[0]
mu = pymc.Uniform("mu",0.00001,1., value=0.13)
nu = pymc.Uniform("nu",0.00001,1., value=0.01)
@pymc.deterministic
def alpha(mu=mu, nu=nu, name='alpha'):
return mu/(nu*nu)
@pymc.deterministic
def beta(mu=mu, nu=nu, name='beta'):
return (1.-mu)/(nu*nu)
thetas=pymc.Container([pymc.Beta("theta_%i" % i, alpha, beta) for i in range(N)])
deaths = pymc.Binomial('deaths', n=tumorn, p=thetas, value=tumory, size=N, observed=True)
我使用此模型的联合后验对alpha,beta作为&#34;新模型的输入&#34;在顶部。这也引出了一个问题,如果我应该在顶部的模型中包括theta1..theta70,因为它们将与alpha和beta一起更新,这要归功于新数据,即n = 14,y = 4的二项式。但我甚至无法获得只有一个先前作为2d样本数组工作的小模型: - (
答案 0 :(得分:1)
我发现了你的问题,因为我遇到了类似的问题。根据pymc.StepMethod.competence的文档,问题是没有内置的采样器处理与随机变量相关的dtype。
我不确定要真正解决这个问题需要做些什么。也许可以扩展其中一个采样器方法来处理特殊类型?
希望有更多pymc mojo的人能够了解需要做的事情。
def competence(s):
"""
This function is used by Sampler to determine which step method class
should be used to handle stochastic variables.
Return value should be a competence
score from 0 to 3, assigned as follows:
0: I can't handle that variable.
1: I can handle that variable, but I'm a generalist and
probably shouldn't be your top choice (Metropolis
and friends fall into this category).
2: I'm designed for this type of situation, but I could be
more specialized.
3: I was made for this situation, let me handle the variable.
In order to be eligible for inclusion in the registry, a sampling
method's init method must work with just a single argument, a
Stochastic object.
If you want to exclude a particular step method from
consideration for handling a variable, do this:
Competence functions MUST be called 'competence' and be decorated by the
'@staticmethod' decorator. Example:
@staticmethod
def competence(s):
if isinstance(s, MyStochasticSubclass):
return 2
else:
return 0
:SeeAlso: pick_best_methods, assign_method
"""