Create theano custom operation with [tt.dmatrix, tt.dmatrix] input

I try to modify the LogLikeGrad class to take two matrices as input.

The LogLikeGrad class is from Using a Blackbox LIkelihood function in the documentation.

I think I did something wrong in specifying the output. But I don’t know what is my mistake.

Test:

import numpy as np
import theano.tensor as tt


class MyOp(tt.Op):
    itypes = [tt.dmatrix, tt.dmatrix]
    otypes = [tt.dmatrix, tt.dmatrix]

    def __init__(self):
        pass

    def perform(self, node, inputs, outputs):
        mat_a, mat_b = inputs
        outputs[0] = 2 * mat_a
        outputs[1] = 3 * mat_b


def main():
    dtype = np.float64
    mat_a = np.ones((3, 3), dtype=dtype)
    mat_b = np.ones((3, 3), dtype=dtype)
    tens_a = tt.as_tensor_variable(mat_a)
    tens_b = tt.as_tensor_variable(mat_b)
    print(tens_a.eval())
    result = MyOp()(tens_a, tens_b)
    # expect to print 2 * mat_a
    print(result[0].eval())


main()

Result:

[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
ERROR (theano.gof.opt): Optimization failure due to: constant_folding
ERROR (theano.gof.opt): node: <__main__.MyOp object at 0x7f067427b5c0>(TensorConstant{(3, 3) of 1.0}, TensorConstant{(3, 3) of 1.0})

... (lots of error messages)

Thanks again.

I think that your problem is that you’re using tensor constants. Those can’t be used as inputs to a function in theano. Try replacing tens_a and tens_b with simple dmatrix.

After replacing tens_a and tens_b by tt.dmatrix, I run into another problem.
The operation returns [None, None] instead of the result that I expect.

Test:

import numpy as np
import theano.tensor as tt
import theano


class MyOp(tt.Op):
    itypes = [tt.dmatrix, tt.dmatrix]
    otypes = [tt.dmatrix, tt.dmatrix]

    def __init__(self):
        pass

    def perform(self, node, inputs, outputs):
        mat_a, mat_b = inputs
        outputs[0] = 2 * mat_a
        outputs[1] = 3 * mat_b



def main():

    tens_a = tt.dmatrix('a')
    tens_b = tt.dmatrix('b')
    funct = MyOp()(tens_a, tens_b)
    f = theano.function([tens_a, tens_b], funct)

    dtype = np.float64
    mat_a = np.ones((3, 3), dtype=dtype)
    mat_b = np.ones((3, 3), dtype=dtype)
    print(f(mat_a, mat_b))


main()

Result:

[None, None]

This works now. But I haven’t figured out how to reuse the memory allocated for output_storage.

Test

# Adapt from the DoubleOp2 in deeplearning.net/software/theano_versions/dev
# /extending/extending_theano.html
import numpy as np
import theano.tensor as tt
import theano


class DoubleOp2(theano.Op):
    # two of instance of this op are equal if the hash of their two __prop__
    # are equal.
    __props__ = ()

    itypes = [tt.dmatrix, tt.dmatrix]
    otypes = [tt.dmatrix, tt.dmatrix]

    def perform(self, node, inputs, output_storage):
        x, y = inputs
        z0 = output_storage[0]
        z0[0] = x * 2
        z1 = output_storage[1]
        z1[0] = y * 2


def main():
    tens_a = tt.dmatrix('a')
    tens_b = tt.dmatrix('b')
    funct = DoubleOp2()(tens_a, tens_b)
    f = theano.function([tens_a, tens_b], funct)

    dtype = np.float64
    mat_a = np.ones((3, 3), dtype=dtype)
    mat_b = np.ones((3, 3), dtype=dtype)
    print(f(mat_a, mat_b))


main()

Result

[array([[2., 2., 2.],
       [2., 2., 2.],
       [2., 2., 2.]]), array([[2., 2., 2.],
       [2., 2., 2.],
       [2., 2., 2.]])]
2 Likes