问题
I am trying to define a custom theano Op with a gradient to use it with pymc3 but I don't understand how to define the grad method.
The code below is where I'm stuck. The function phi() is a mock function (in practice, it is an external program); for a scalar input x it returns a vector (phi_0(x), phi_1(x), ...). The function phi_diff() (also a mock function) returns the vector (dphi_0/dx, dphi_1/dx, ...).
I wrapped phi() and phi_diff() in a theano.Op object but my implementation of the grad function does not work. The documentation of theano contains simpler examples, I don't understand how to adapt them in this case. Any help would be greatly appreciated.
import numpy as np
import theano.tensor as T
import theano
theano.config.optimizer = "None"
theano.config.exception_verbosity = "high"
def phi(x):
    return np.arange(n) * x
def phi_diff(x):
    return np.arange(n)
class PhiOp(theano.Op):
    itypes = [theano.tensor.dscalar]
    otypes = [theano.tensor.dvector]
    def perform(self, node, inputs, output_storage):
        x = inputs[0]
        output_storage[0][0] = phi(x)
    def grad(self, inputs, output_grads):
        x = inputs[0]
        # ???
        return [PhiDiffOp()(x) * output_grads[0]]
class PhiDiffOp(theano.Op):
    itypes = [theano.tensor.dscalar]
    otypes = [theano.tensor.dvector]
    def perform(self, node, inputs, output_storage):
        x = inputs[0]
        output_storage[0][0] = phi_diff(x)
n = 5
x = 777.
phi_op = PhiOp()
x_tensor = T.dscalar("x_tensor")
phi_func = theano.function([x_tensor], phi_op(x_tensor))
np.testing.assert_allclose(phi_func(x), phi(x))
T.jacobian(phi_op(x_tensor), x_tensor)
回答1:
Found the solution, changes below:
def phi_diff(x):
    return np.arange(n, dtype=np.float_)
class PhiOp(theano.Op):
    def grad(self, inputs, output_grads):
        x = inputs[0]
        gg = (PhiDiffOp()(x) * output_grads[0]).sum()
        return [gg]
来源:https://stackoverflow.com/questions/52759259/defining-grad-of-a-custom-op-theano