如何使用pymc3拟合属于实例的方法?

Sté*_*ane 8 pymc3

我没有使用PyMc3将属于类实例的方法作为确定性函数.你能告诉我怎么做吗?

为简单起见,我的案例总结如下,并附有一个简单的例子.实际上,我的约束是一切都是通过GUI完成的,像'find_MAP'这样的动作应该在链接到pyqt按钮的方法中.

我想在数据点上安装函数'FunctionIWantToFit'.问题,以下代码:

import numpy as np
import pymc3 as pm3
from scipy.interpolate import interp1d
import theano.tensor as tt
import theano.compile

class cprofile:
    def __init__(self):
        self.observed_x = np.array([0.3,1.4,3.1,5,6.8,9,13.4,17.1])
        self.observations = np.array([6.25,2.75,1.25,1.25,1.5,1.75,1.5,1])
        self.x = np.arange(0,18,0.5)

    @theano.compile.ops.as_op(itypes=[tt.dscalar,tt.dscalar,tt.dscalar],
                              otypes=[tt.dvector])
    def FunctionIWantToFit(self,t,y,z):
        # can be complicated but simple in this example
        # among other things, this FunctionIWantToFit depends on a bunch of 
        # variables and methods that belong to this instance of the class cprofile,
        # so it cannot simply be put outside the class ! (like in the following example)
        val=t+y*self.x+z*self.x**2
        interp_values = interp1d(self.x,val)
        return interp_values(self.observed_x)

    def doMAP(self):
        model = pm3.Model()
        with model:
            t = pm3.Uniform("t",0,5)
            y = pm3.Uniform("y",0,5)
            z = pm3.Uniform("z",0,5)
            MyModel = pm3.Deterministic('MyModel',self.FunctionIWantToFit(t,y,z))
            obs = pm3.Normal('obs',mu=MyModel,sd=0.1,observed=self.observations)
            start = pm3.find_MAP()
            print('start: ',start)

test=cprofile()
test.doMAP()
Run Code Online (Sandbox Code Playgroud)

给出以下错误:

Traceback (most recent call last):

  File "<ipython-input-15-3dfb7aa09f84>", line 1, in <module>
    runfile('/Users/steph/work/profiles/GUI/pymc3/so.py', wdir='/Users/steph/work/profiles/GUI/pymc3')

  File "/Users/steph/anaconda/lib/python3.5/site-packages/spyder/utils/site/sitecustomize.py", line 866, in runfile
    execfile(filename, namespace)

  File "/Users/steph/anaconda/lib/python3.5/site-packages/spyder/utils/site/sitecustomize.py", line 102, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "/Users/steph/work/profiles/GUI/pymc3/so.py", line 44, in <module>
    test.doMAP()

  File "/Users/steph/work/profiles/GUI/pymc3/so.py", line 38, in doMAP
    MyModel = pm3.Deterministic('MyModel',self.FunctionIWantToFit(x,y,z))

  File "/Users/steph/anaconda/lib/python3.5/site-packages/theano/gof/op.py", line 668, in __call__
    required = thunk()

  File "/Users/steph/anaconda/lib/python3.5/site-packages/theano/gof/op.py", line 912, in rval
    r = p(n, [x[0] for x in i], o)

  File "/Users/steph/anaconda/lib/python3.5/site-packages/theano/compile/ops.py", line 522, in perform
    outs = self.__fn(*inputs)

TypeError: FunctionIWantToFit() missing 1 required positional argument: 'z'
Run Code Online (Sandbox Code Playgroud)

怎么了 ?

备注1:我系统地收到有关'FunctionIWantToFit'的最后一个参数的错误消息.这里是'z'但是如果我从签名中删除z,则错误消息涉及'y'(除了变量名称之外相同).如果我在签名中添加第四个变量'w',则错误消息涉及'w'(除了变量名称之外相同).

rk2:看起来我在'theano'或'pymc3'中遗漏了一些非常基本的东西,因为当我把'FunctionIWantToFit'放在课外时,它可以工作.请参阅以下示例.

class cprofile:
    def __init__(self):
        self.observations = np.array([6.25,2.75,1.25,1.25,1.5,1.75,1.5,1])

    def doMAP(self):
        model = pm3.Model()
        with model:
            t = pm3.Uniform("t",0,5)
            y = pm3.Uniform("y",0,5)
            z = pm3.Uniform("z",0,5)
            MyModel = pm3.Deterministic('MyModel',FunctionIWantToFit(t,y,z))
            obs = pm3.Normal('obs',mu=MyModel,sd=0.1,observed=self.observations)
            start = pm3.find_MAP()
            print('start: ',start)

@theano.compile.ops.as_op(itypes=[tt.dscalar,tt.dscalar,tt.dscalar],
                              otypes=[tt.dvector])
def FunctionIWantToFit(t,y,z):
        observed_x = np.array([0.3,1.4,3.1,5,6.8,9,13.4,17.1])
        x = np.arange(0,18,0.5)
        val=t+y*x+z*x**2
        interp_values = interp1d(x,val)
        return interp_values(observed_x)

test=cprofile()
test.doMAP()
Run Code Online (Sandbox Code Playgroud)

得到:

Warning: gradient not available.(E.g. vars contains discrete variables). MAP estimates may not be accurate for the default parameters. Defaulting to non-gradient minimization fmin_powell.
WARNING:pymc3:Warning: gradient not available.(E.g. vars contains discrete variables). MAP estimates may not be accurate for the default parameters. Defaulting to non-gradient minimization fmin_powell.
Optimization terminated successfully.
         Current function value: 1070.673818
         Iterations: 4
         Function evaluations: 179
start:  {'t_interval_': array(-0.27924150484602733), 'y_interval_': array(-9.940000425802811), 'z_interval_': array(-12.524909223913992)}
Run Code Online (Sandbox Code Playgroud)

除了我不知道如何在几个模块中进行大的修改之后如何做到这一点,因为真正的'FunctionIWantToFit'依赖于属于类配置文件的这个实例的一堆变量和方法.

事实上,我甚至不确定我是怎么做的,因为'FunctionIWantToFit'应该在参数中有对象(我目前正在使用self)并且我不确定如何使用theano装饰器.

所以我宁愿避免这种解决方案......除非必要.然后我需要解释如何实现它......


于2017年4月9日添加:

即使没有插值问题,它也不起作用,因为我必须错过了与theano和/或pymc3明显的东西.请问你能解释一下这个问题吗?我只想比较模型和数据.首先,被pymc2困扰是如此的耻辱.; 第二,我确信我不是唯一一个有这样一个基本问题的人.

例如,让我们考虑这个基本代码的变体:

import numpy as np
import theano
import pymc3
theano.config.compute_test_value = 'ignore'
theano.config.on_unused_input = 'ignore'

class testclass:
    x = np.arange(0,18,0.5)
    observed_x = np.array([0.3,1.4,3.1,5,6.8,9,13.4,17.1])
    observations = np.array([6.25,2.75,1.25,1.25,1.5,1.75,1.5,1])

    def testfunc(self,t,y,z):
        t2 = theano.tensor.dscalar('t2')
        y2 = theano.tensor.dscalar('y2')
        z2 = theano.tensor.dscalar('z2')
        val = t2 + y2 * self.observed_x + z2 * self.observed_x**2
        f = theano.function([t2,y2,z2],val)
        return f

test=testclass()
model = pymc3.Model()
with model:
    t = pymc3.Uniform("t",0,5)
    y = pymc3.Uniform("y",0,5)
    z = pymc3.Uniform("z",0,5)

with model:
   MyModel = pymc3.Deterministic('MyModel',test.testfunc(t,y,z))

with model:
   obs = pymc3.Normal('obs',mu=MyModel,sd=0.1,observed=test.observations)
Run Code Online (Sandbox Code Playgroud)

此代码在最后一行失败,并显示错误消息: TypeError: unsupported operand type(s) for -: 'TensorConstant' and 'Function'

如果我将'testfunc'改为:

def testfunc(self,t,y,z):
    t2 = theano.tensor.dscalar('t2')
    y2 = theano.tensor.dscalar('y2')
    z2 = theano.tensor.dscalar('z2')
    val = t2 + y2 * self.observed_x + z2 * self.observed_x**2
    f = theano.function([t2,y2,z2],val)
    fval = f(t,y,z,self.observed_x)
    return fval
Run Code Online (Sandbox Code Playgroud)

代码在'MyModel ='行失败并出错 TypeError: ('Bad input argument to theano function with name "/Users/steph/work/profiles/GUI/pymc3/theanotest170409.py:32" 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?')

如果我回到原来的'testfunc'但是改变了最后的'with model'行:

with model:
   fval = test.testfunc(t,y,z)
   obs = pymc3.Normal('obs',mu=fval,sd=0.1,observed=test.observations)
Run Code Online (Sandbox Code Playgroud)

错误与第一个错误相同.

我在这里只展示了3次尝试,但我想强调一下,我尝试了很多种组合,在这几种情况下,这些组合更简单,更简单.我感觉pymc3显示了一个巨大的精神变化,与pymc2相比,我没有得到,并且记录不足...

Sté*_*ane 1

我最终收敛到下面的成功代码:

\n\n
import numpy as np\nimport theano\nfrom scipy.interpolate import interp1d\nimport pymc3 as pm3\ntheano.config.compute_test_value = \'ignore\'\ntheano.config.on_unused_input = \'ignore\'\n\nclass cprofile:\n    observations = np.array([6.25,2.75,1.25,1.25,1.5,1.75,1.5,1])\n    x = np.arange(0,18,0.5)\n    observed_x = np.array([0.3,1.4,3.1,5,6.8,9,13.4,17.1])    \n\n    def doMAP(self):\n        model = pm3.Model()\n        with model:\n            t = pm3.Uniform("t",0,5)\n            y = pm3.Uniform("y",0,5)\n            z = pm3.Uniform("z",0,5)\n            obs=pm3.Normal(\'obs\',\n              mu=FunctionIWantToFit(self)(t,y,z),\n              sd=0.1,observed=self.observations)\n            start = pm3.find_MAP()\n            print(\'start: \',start)\n\nclass FunctionIWantToFit(theano.gof.Op):\n    itypes=[theano.tensor.dscalar,\n            theano.tensor.dscalar,\n            theano.tensor.dscalar]\n    otypes=[theano.tensor.dvector]\n\n    def __init__(self, cp):\n        self.cp = cp # note cp is an instance of the \'cprofile\' class\n\n    def perform(self,node, inputs, outputs):\n        t, y, z = inputs[0], inputs[1], inputs[2]\n\n        xxx = self.cp.x\n        temp = t+y*xxx+z*xxx**2\n        interpolated_concentration = interp1d(xxx,temp)   \n        outputs[0][0] = interpolated_concentration(self.cp.observed_x)\n\ntestcp=cprofile()\ntestcp.doMAP()\n
Run Code Online (Sandbox Code Playgroud)\n\n

感谢达里奥的回答,因为我自己理解第一个答案太慢了。我回顾了一下,但我强烈认为 pymc3 文档非常不清楚。它应该包含非常简单且说明性的示例。

\n\n

然而,我没有\xe2\x80\x99t 成功地按照克里斯的评论做任何有效的事情。有人可以解释和/或举个例子吗?

\n\n

另一件事:我不知道我上面的例子是否有效或者可以简化。特别是它给我的印象是实例 \xe2\x80\x98testcp\xe2\x80\x99 在内存中复制了两次。欢迎更多评论/答案,以走得更远。

\n