2016-09-02 12 views
0

私はpymc3を使って複雑なカスタム尤度関数を定義しようとしています。尤度関数には多くの反復が必要なので、私はtheanoのscanメソッドを使ってtheano内で反復を直接定義しようとしています。ここでは、私が直面している課題を説明する非常に単純化された例があります。私が定義しようとしている(偽の)尤度関数は、単純に2つのpymc3確率変数pとthetaの和です。もちろん、私は単純にp + thetaを返すことができますが、実際に作成しようとしている尤度関数はもっと複雑で、繰り返し回数が多いのでtheano.scanを使う必要があると思います。pymc3 theano関数の使用

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?') 

私は問題がラインに 結果= get_ll(P、シータ)を発生することを理解し

pとシータがあるため、 pymc3.TransformedRV型の関数であり、theano関数への入力は、単純なnumpy配列のスカラー数である必要があるということです。しかし、pymc3 TransformedRVは、ランダム変数自体の現在の値を得る明白な方法を持っていないようです。

入力としてpymc3確率変数をとるtheano関数の使用を伴う対数尤度関数を定義することは可能ですか?

+0

[PyMC3リポジトリ](https://github.com/pymc-devs/pymc3/search?q=scan&type=Code&utf8=%E2%9C%93)でサンプルを検索しましたか? – aloctavodia

答えて

0

問題は、th.function get_llが数値配列を入力とするコンパイルされたtheano関数だということです。代わりに、pymc3はそれにシンボリック変数(theano tensor)を送ります。だからあなたはエラーを受けている。

あなたの解決策については、p + thetaを返すだけでいいと言えるでしょう。あなたのログにスキャンとそれ以外のものがある場合は、関心のあるスキャン変数を返します。ここでtheano関数をコンパイルする必要はありません。たとえば、あなたは(非現実的なおもちゃの一例として)ベクトルの各要素に1を追加したい場合は、あなたがどうなる:

def logp(X): 
    the_sum, the_sum_upd = th.scan(lambda x: x+1, sequences=[X]) 
    return the_sum 

言われていること、あなたはグラデーションが必要な場合、あなたはあなたのthe_sumを計算する必要があります変数をtheano Opに入力し、それに沿ってgrad()メソッドを提供します(答えはhereです)。グラデーションを必要としない場合は、Python(またはC、numba、cython、パフォーマンス用)やas_opデコレータを使用する方が良いでしょう。

関連する問題