Python 如何在PyMC中定义一般确定性函数

Python 如何在PyMC中定义一般确定性函数,python,bayesian,pymc,mcmc,pymc3,Python,Bayesian,Pymc,Mcmc,Pymc3,在我的模型中,我需要使用复杂的python函数从一组父变量中获取确定性变量的值 @pm.theano.compile.ops.as_op(itypes=[t.dscalar, t.dscalar, t.dscalar],otypes=[t.dvector]) 有可能吗 下面是一个pyMC3代码,它显示了我在一个简化案例中尝试做的事情 import numpy as np import pymc as pm #Predefine values on two parameter Grid (x

在我的模型中,我需要使用复杂的python函数从一组父变量中获取确定性变量的值

@pm.theano.compile.ops.as_op(itypes=[t.dscalar, t.dscalar, t.dscalar],otypes=[t.dvector])
有可能吗

下面是一个pyMC3代码,它显示了我在一个简化案例中尝试做的事情

import numpy as np
import pymc as pm


#Predefine values on two parameter Grid (x,w) for a set of i values (1,2,3)
idata = np.array([1,2,3])
size= 20
gridlength = size*size
Grid = np.empty((gridlength,2+len(idata)))
for x in range(size):
    for w in range(size):
        # A silly version of my real model evaluated on grid.
        Grid[x*size+w,:]= np.array([x,w]+[(x**i + w**i) for i in idata])

# A function to find the nearest value in Grid and return its product with third variable z
def FindFromGrid(x,w,z):
    return Grid[int(x)*size+int(w),2:] * z

#Generate fake Y data with error
yerror = np.random.normal(loc=0.0, scale=9.0, size=len(idata))
ydata = Grid[16*size+12,2:]*3.6 + yerror  # ie. True x= 16, w= 12 and z= 3.6


with pm.Model() as model:

    #Priors
    x = pm.Uniform('x',lower=0,upper= size)
    w = pm.Uniform('w',lower=0,upper =size)
    z = pm.Uniform('z',lower=-5,upper =10)

    #Expected value
    y_hat = pm.Deterministic('y_hat',FindFromGrid(x,w,z))

    #Data likelihood
    ysigmas = np.ones(len(idata))*9.0 
    y_like = pm.Normal('y_like',mu= y_hat, sd=ysigmas, observed=ydata)

    # Inference...
    start = pm.find_MAP() # Find starting value by optimization
    step = pm.NUTS(state=start) # Instantiate MCMC sampling algorithm
    trace = pm.sample(1000, step, start=start, progressbar=False) # draw 1000 posterior samples using NUTS sampling


print('The trace plot')
fig = pm.traceplot(trace, lines={'x': 16, 'w': 12, 'z':3.6})
fig.show()
运行此代码时,在y_hat阶段出现错误,因为
FindFromGrid(x,w,z)
函数中的
int()
函数需要整数而不是FreeRV

从预先计算的网格中查找
y_-hat
非常重要,因为我的y_-hat实际模型没有解析形式来表示

我之前尝试过使用OpenBUGS,但我发现在OpenBUGS中不可能做到这一点。在PyMC中可能吗

更新 基于pyMC github页面中的一个示例,我发现需要将以下装饰器添加到我的
FindFromGrid(x,w,z)
函数中

@pm.theano.compile.ops.as_op(itypes=[t.dscalar, t.dscalar, t.dscalar],otypes=[t.dvector])
这似乎解决了上述问题。但我不能再使用坚果采样器了,因为它需要梯度

大都会似乎没有融合


在这样的场景中,我应该使用哪一步方法?

您使用
as\u op
找到了正确的解决方案

关于收敛性:您是否碰巧使用了
pm.Metropolis()
而不是
pm.NUTS()
?无法收敛的一个原因是,
Metropolis()
默认情况下,关节空间中的样本,而Metropolis中的Gibbs通常更有效(这是pymc2中的默认值)。话虽如此,我还是合并了这个:它改变了
Metropolis
Slice
采样器的默认行为,使其在默认情况下是非阻塞的(Gibbs内部也是如此)。其他采样器,如
螺母
,主要用于对关节空间进行采样,但默认情况下仍为阻塞。您始终可以使用kwarg
blocked=True
显式设置此选项


无论如何,请使用最新的主机更新pymc,并查看收敛是否有所改善。如果没有,请尝试
切片
采样器。

谢谢您的帮助。我猜,在我上面的示例模型中发生的是,变量高度相关。因此,在经历了几条MC链之后,它在某个时候陷入了困境。有没有办法增加跳跃的步长?我还想知道为什么在使用pm.find_MAP()时,我的函数会出现一个错误no grad()属性,如果它使用的是Nelder Mead优化,它不需要导数。是的,
find_MAP()
与Nelder Mead一起应该可以工作。你能在github上用一些代码来重现这个问题吗?关于卡住,这是MCMC的痛苦。如果相关性是个问题,你可以尝试调整Metropolis Hastings的提案分布,或者只是运行更多的样本。谢谢。我将在github上发布一个问题。