我正在尝试使用pymc3定义一个复杂的自定义似然函数。似然函数涉及大量迭代,因此我尝试使用theano的扫描方法直接在theano中定义迭代。这里有一个非常简单的例子,它说明了我所面临的挑战。我试图定义的(伪)似然函数是两个pymc3随机变量p和θ的和。当然,我可以简单地返回p+theta,但我尝试编写的实际似然函数更复杂,而且我认为我需要使用theano.scan,因为它涉及很多迭代。
import pymc3 as pm
from pymc3 import Model, Uniform, DensityDist
import theano.tensor as T
import theano
import numpy as np
### theano test
theano.config.compute_test_value = 'raise'
X = np.asarray([[1.0,2.0,3.0],[1.0,2.0,3.0]])
### pymc3 implementation
with Model() as bg_model:
p = pm.Uniform('p', lower = 0, upper = 1)
theta = pm.Uniform('theta', lower = 0, upper = .2)
def logp(X):
f = p+theta
print("f",f)
get_ll = theano.function(name='get_ll',inputs = [p, theta], outputs = f)
print("p keys ",p.__dict__.keys())
print("theta keys ",theta.__dict__.keys())
print("p name ",p.name,"p.type ",p.type,"type(p)",type(p),"p.tag",p.tag)
result=get_ll(p, theta)
print("result",result)
return result
y = pm.DensityDist('y', logp, observed = X) # Nx4 y = f(f,x,tx,n | p, theta)当我运行这段代码时,我得到以下错误:
TypeError: ('Bad input argument to theano function with name "get_ll" at index 0(0-based)', 'Expected an array-like object, but found a Variable: maybe you are trying to call a function on a (possibly shared) variable instead of a numeric array?')我知道这个问题发生在result=get_ll(p,theta)行
因为p和theta是pymc3.TransformmedRV类型,所以theano函数的输入必须是简单numpy数组的标量数。然而,pymc3 TransformedRV似乎没有任何明显的方法来获得随机变量本身的当前值。
有没有可能定义一个对数似然函数,它涉及到将pymc3随机变量作为输入的theano函数的使用?
发布于 2016-12-13 22:56:36
问题是你的th.function get_ll是一个编译过的theano函数,它接受数值数组作为输入。相反,pymc3向它发送了一个符号变量(theano张量)。这就是你得到这个错误的原因。
至于您的解决方案,您说得对,只需返回p+theta就可以了。如果您的日志中有扫描和其他内容,那么您将返回感兴趣的scan变量;这里不需要编译theano函数。例如,如果您想将向量的每个元素加1(作为一个不切实际的玩具示例),您将执行以下操作:
def logp(X):
the_sum, the_sum_upd = th.scan(lambda x: x+1, sequences=[X])
return the_sum也就是说,如果你需要梯度,你需要在theano Op中计算你的the_sum变量,并提供一个grad()方法(你可以在answer here上看到一个玩具示例)。如果不需要渐变,最好使用python (或C、numba、cython,以提高性能)并使用as_op装饰器。
https://stackoverflow.com/questions/39297736
复制相似问题