2017-02-22 14 views
0

Я попытался реализовать пользовательскую Op, которой я получаю ошибку «Плохой ввод аргумента функции anano». Вот код. Проблема, как я понимаю, заключается в следующем: как преобразовать переменные PyMC3 в понятный тип anano?Theano custom Op for PyMC3

import numpy as np 
import theano 
import theano.tensor as t 
from theano import config 
config.compute_test_value = 'off' 

#true_Data = [1,2] 
#values=[] 

class trial_Op(theano.Op): 
    __props__ =() 
    itypes = [t.dmatrix, t.dmatrix, t.dmatrix] 
    otypes = [t.dmatrix] 

    def perform(self,node,inputs,output_storage): 
     x0 = inputs[0] 
     x1 = inputs[1] 
     x2 = inputs[2] 
     z = output_storage[0] 
     z[0] = np.add(x0,x1) 
     z[0] = np.add(z[0],x2) 

    def grad(self,inputs,output_grads): 
     return output_grads[0] 
Trial_Op = trial_Op() 

x1 = t.dmatrix() 
x2 = t.dmatrix() 
x3 = t.dmatrix() 
f = theano.function([x1,x2,x3], trial_Op()(x1,x2,x3)) 

# the Op works for the 
#inp1 = np.random.rand(3,1) # a 2d matrix 
#inp2 = np.random.rand(3,1) # a 2d matrix 
#inp3 = np.array([[-40]])    # a constant 
#print("Op application gives = ", f(inp1,inp2,inp3)) 


import pymc3 as pm 
true_Data = [[1]] 

with pm.Model() as model: 
    x1 = pm.Normal('x1', mu = 0, sd = 0.1) 
    x2 = pm.Normal('x2', mu = 3, sd = 0.5) 
    x3 = np.asarray([[4]], dtype='float64') 
# x1 = x1.reshape(1,1) 
# x2 = x2.reshape(1,1) 
    sum_of_x1_x2_x3 = f(x1,x2,x3) 
    z = pm.Normal('z', sum_of_x1_x2_x3, observed = true_Data) 
    start = {'x1':[[0.1]], 'x2':[[0.1]]} 
    step = pm.Metropolis() 
    trace = pm.sample(100, step, start) 

pm.traceplot(trace) 

ответ

0

Я думаю, что я могу ответить на ваш вопрос.

Во-первых,, вы не должны использовать f = theano.function([x1,x2,x3], trial_Op()(x1,x2,x3)). Как только он определен, f принимает числовые значения в качестве аргументов. Однако в модели pymc3 x1 и x2, определенные как Normal, не являются числовыми, но символическими. Таким образом, это вызовет ошибку, с которой вы столкнулись. Если вы знакомы с @as_op метод, задокументированный в учебнике, решение прост: изменить sum_of_x1_x2_x3 = f(x1,x2,x3) на sum_of_x1_x2_x3 = Trial_Op(x1,x2,x3);

второй адрес, в вашем коде, кажется dmatrix type не требуется. так что я изменить код следующее:

N = 20 #data array length 

class Trial_Op(theano.Op): 
    __props__ =() 
    itypes = [t.dscalar, t.dscalar] 
    otypes = [t.dvector] #if the data has multiple values i.e. data array 

    def perform(self,node,inputs,output_storage): 
     x0 = inputs[0] 
     x1 = inputs[1] 

     f = np.add(x0,x1) 
     out = np.empty(N) 
     out[:] = f 
     z = output_storage[0] 
     z[0] = out 


trial_Op = Trial_Op() 


import pymc3 as pm 
true_Data = np.random.normal(2,1,N) 

with pm.Model() as model: 
    x1 = pm.Normal('x1', mu = 0, sd = 0.1) 
    x2 = pm.Normal('x2', mu = 3, sd = 0.5)  

    mu = trial_Op(x1, x2) 
    z = pm.Normal('z', mu = mu, sd = 1., observed = true_Data) 

    step = pm.Metropolis() 
    trace = pm.sample(10000, step) 

pm.traceplot(trace) 

Примечание в пользовательской функции, то otypes является dvector удовлетворить mu в z = pm.Normal('z', mu = mu, sd = 1., observed = true_Data). А номер образца расширяется до 10000. В результате изображение показывает:

result

Однако, я не знаю, как определить метод grad() в пользовательской функции Theano. Может быть, позже кто-то или я решит его, чтобы включить метод выборки NUTS в модели :).

Смежные вопросы