我試圖寫一個自定義Theano歐普其數字集成了兩個值之間的函數。 Op是一種PyMC3的定製可能性,涉及一些積分的數值計算。我不能簡單地使用@as_op裝飾器,因爲我需要使用HMC來執行MCMC步驟。任何幫助將不勝感激,因爲這個問題似乎已經走到了好幾次,但一直沒有得到解決(例如https://stackoverflow.com/questions/36853015/using-theano-with-numerical-integration,Theano: implementing an integral function)。定製Theano運算數值積分
顯然,一個解決辦法是寫中Theano數值積分,但是這似乎是白費力氣的時候很好的集成已經上市,例如通過scipy.integrate。
爲了保持作爲一個最小的例子,讓我們只是嘗試和0和1之間的整合運算內部函數。以下內容集成了Op之外的Theano函數,並且在我的測試結束後生成正確的結果。
import theano
import theano.tensor as tt
from scipy.integrate import quad
x = tt.dscalar('x')
y = x**4 # integrand
f = theano.function([x], y)
print f(0)
print f(1)
ans = integrate.quad(f, 0, 1)[0]
print ans
但是,嘗試在Op中進行整合看起來要困難得多。我現在最大的努力爲:
import numpy as np
import theano
import theano.tensor as tt
from scipy import integrate
class IntOp(theano.Op):
__props__ =()
def make_node(self, x):
x = tt.as_tensor_variable(x)
return theano.Apply(self, [x], [x.type()])
def perform(self, node, inputs, output_storage):
x = inputs[0]
z = output_storage[0]
f_to_int = theano.function([x], x)
z[0] = tt.as_tensor_variable(integrate.quad(f_to_int, 0, 1)[0])
def infer_shape(self, node, i0_shapes):
return i0_shapes
def grad(self, inputs, output_grads):
ans = integrate.quad(output_grads[0], 0, 1)[0]
return [ans]
intOp = IntOp()
x = tt.dmatrix('x')
y = intOp(x)
f = theano.function([x], y)
inp = np.asarray([[2, 4], [6, 8]], dtype=theano.config.floatX)
out = f(inp)
print inp
print out
其中提供了以下錯誤:
Traceback (most recent call last):
File "stackoverflow.py", line 35, in <module>
out = f(inp)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/function_module.py", line 871, in __call__
storage_map=getattr(self.fn, 'storage_map', None))
File "/usr/local/lib/python2.7/dist-packages/theano/gof/link.py", line 314, in raise_with_op
reraise(exc_type, exc_value, exc_trace)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/function_module.py", line 859, in __call__
outputs = self.fn()
File "/usr/local/lib/python2.7/dist-packages/theano/gof/op.py", line 912, in rval
r = p(n, [x[0] for x in i], o)
File "stackoverflow.py", line 17, in perform
f_to_int = theano.function([x], x)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 320, in function
output_keys=output_keys)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 390, in pfunc
for p in params]
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in _pfunc_param_to_in
raise TypeError('Unknown parameter type: %s' % type(param))
TypeError: Unknown parameter type: <type 'numpy.ndarray'>
Apply node that caused the error: IntOp(x)
Toposort index: 0
Inputs types: [TensorType(float64, matrix)]
Inputs shapes: [(2, 2)]
Inputs strides: [(16, 8)]
Inputs values: [array([[ 2., 4.],
[ 6., 8.]])]
Outputs clients: [['output']]
Backtrace when the node is created(use Theano flag traceback.limit=N to make it longer):
File "stackoverflow.py", line 30, in <module>
y = intOp(x)
File "/usr/local/lib/python2.7/dist-packages/theano/gof/op.py", line 611, in __call__
node = self.make_node(*inputs, **kwargs)
File "stackoverflow.py", line 11, in make_node
return theano.Apply(self, [x], [x.type()])
HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.
我感到意外,特別是類型錯誤,因爲我以爲我已經轉換的output_storage變量爲張量,但它似乎相信它仍然是一個ndarray。
在'perform'方法中,您應該只執行* numerical *計算。但是,在'grad'方法中,您應該創建符號圖。 – Kh40tiK
謝謝你看看這個。我認爲你指的是perform()中的theano.function和as_tensor_variable行?這是因爲集成期望Python函數作爲其第一個參數並返回一個數組,其第0個值是積分值。因爲Op的簽名需要在輸出中使用Theano變量,所以我必須將其轉換,但我不確定我是否做得對! – tmm13
目前還不清楚你想要做什麼。在你的例子中積分只是一個數字,在theano中輸入一個數字並不是很困難。 :-)你是否想這樣編碼:$ f(x)= \ int g(x,y)dy $?如果是這樣,您需要將特定x的實際計算放在執行中,並返回指定grad中導數的運算符。 – aseyboldt