Table Of Contents

Previous topic

toolbox – [doc TODO]

Next topic

scan – Looping in Theano

This Page

type – Interface for types of variables

Reference

WRITEME Defines the Type class.

class theano.gof.type.CLinkerType

Interface specification for Types that can be arguments to a CLinkerOp.

A CLinkerType instance is mainly reponsible for providing the C code that interfaces python objects with a C CLinkerOp implementation.

See WRITEME for a general overview of code generation by CLinker.

c_cleanup(name, sub)

Optional: Return c code to clean up after c_extract.

This returns C code that should deallocate whatever c_extract allocated or decrease the reference counts. Do not decrease py_%(name)s’s reference count.

WRITEME

Parameters :
  • name: WRITEME

    WRITEME

  • sub: WRITEME

    WRITEME

Exceptions :
  • MethodNotDefined: Subclass does not implement this method
c_code_cache_version()

Return a tuple of integers indicating the version of this Type.

An empty tuple indicates an ‘unversioned’ Type that will not be cached between processes.

The cache mechanism may erase cached modules that have been superceded by newer versions. See ModuleCache for details.

c_declare(name, sub)

Required: Return c code to declare variables that will be instantiated by c_extract.

Example: .. code-block: python

return “PyObject ** addr_of_%(name)s;”
Parameters:
  • name (string) – the name of the PyObject * pointer that will the value for this Type
  • sub (dict string -> string) – a dictionary of special codes. Most importantly sub[‘fail’]. See CLinker for more info on sub and fail.
Note :

It is important to include the name inside of variables which are declared here, so that name collisions do not occur in the source file that is generated.

Note :

The variable called name is not necessarily defined yet where this code is inserted. This code might be inserted to create class variables for example, whereas the variable name might only exist inside certain functions in that class.

Todo :

Why should variable declaration fail? Is it even allowed to?

Exceptions :
  • MethodNotDefined: Subclass does not implement this method
c_extract(name, sub)

Required: Return c code to extract a PyObject * instance.

The code returned from this function must be templated using %(name)s, representing the name that the caller wants to call this Variable. The Python object self.data is in a variable called “py_%(name)s” and this code must set the variables declared by c_declare to something representative of py_%(name)s. If the data is improper, set an appropriate exception and insert “%(fail)s”.

Todo :Point out that template filling (via sub) is now performed by this function. –jpt

Example: .. code-block: python

return “if (py_%(name)s == Py_None)” + addr_of_%(name)s = &py_%(name)s;” + “else” + { PyErr_SetString(PyExc_ValueError, ‘was expecting None’); %(fail)s;}”
Parameters:
  • name (string) – the name of the PyObject * pointer that will store the value for this Type
  • sub (dict string -> string) – a dictionary of special codes. Most importantly sub[‘fail’]. See CLinker for more info on sub and fail.
Exceptions :
  • MethodNotDefined: Subclass does not implement this method
c_extract_out(name, sub)

Optional: C code to extract a PyObject * instance.

Unlike c_extract, c_extract_out has to accept Py_None, meaning that the variable should be left uninitialized.

c_init(name, sub)

Required: Return c code to initialize the variables that were declared by self.c_declare()

Example: .. code-block: python

return “addr_of_%(name)s = NULL;”
Note :The variable called name is not necessarily defined yet where this code is inserted. This code might be inserted in a class constructor for example, whereas the variable name might only exist inside certain functions in that class.
Todo :Why should variable initialization fail? Is it even allowed to?
c_is_simple()

Optional: Return True for small or builtin C types.

A hint to tell the compiler that this type is a builtin C type or a small struct and that its memory footprint is negligible. Simple objects may be passed on the stack.

c_literal(data)

Optional: WRITEME

Parameters :
  • data: WRITEME

    WRITEME

Exceptions :
  • MethodNotDefined: Subclass does not implement this method
c_sync(name, sub)

Required: Return c code to pack C types back into a PyObject.

The code returned from this function must be templated using “%(name)s”, representing the name that the caller wants to call this Variable. The returned code may set “py_%(name)s” to a PyObject* and that PyObject* will be accessible from Python via variable.data. Do not forget to adjust reference counts if “py_%(name)s” is changed from its original value.

Parameters :
  • name: WRITEME

    WRITEME

  • sub: WRITEME

    WRITEME

Exceptions :
  • MethodNotDefined: Subclass does not implement this method
class theano.gof.type.Generic

Represents a generic Python object.

This class implements the PureType and CLinkerType interfaces for generic PyObject instances.

EXAMPLE of what this means, or when you would use this type.

WRITEME

class theano.gof.type.PureType

Interface specification for variable type instances.

A Type instance is mainly reponsible for two things:

  • creating Variable instances (conventionally, __call__ does this), and
  • filtering a value assigned to a Variable so that the value conforms to restrictions imposed by the type (also known as casting, this is done by filter),
class Constant(type, data, name=None)

A Constant is a Variable with a value field that cannot be changed at runtime.

Constant nodes make eligible numerous optimizations: constant inlining in C code, constant folding, etc.

clone()

We clone this object, but we don’t clone the data to lower memory requirement We suppose that the data will never change.

value

read-only data access method

class PureType.Variable(type, owner=None, index=None, name=None)

A Variable is a node in an expression graph that represents a variable.

The inputs and outputs of every Apply (theano.gof.Apply) are Variable instances. The input and output arguments to create a function are also Variable instances. A Variable is like a strongly-typed variable in some other languages; each Variable contains a reference to a Type instance that defines the kind of value the Variable can take in a computation.

A Variable is a container for four important attributes:

  • type a Type instance defining the kind of value this Variable can have,
  • owner either None (for graph roots) or the Apply instance of which self is an output,
  • index the integer such that owner.outputs[index] is this_variable (ignored if owner is None)
  • name a string to use in pretty-printing and debugging.

There are a few kinds of Variables to be aware of: A Variable which is the output of a symbolic computation has a reference to the Apply instance to which it belongs (property: owner) and the position of itself in the owner’s output list (property: index).

  • Variable (this base type) is typically the output of a symbolic computation,
  • Constant (a subclass) which adds a default and un-replaceable value, and requires that owner is None
  • TensorVariable subclass of Variable that represents a numpy.ndarray object
  • SharedTensorVariable Shared version of TensorVariable
  • SparseVariable subclass of Variable that represents a scipy.sparse.{csc,csr}_matrix object
  • CudaNdarrayVariable subclass of Variable that represents our object on the GPU that is a subset of numpy.ndarray
  • RandomVariable

A Variable which is the output of a symbolic computation will have an owner not equal to None.

Using the Variables’ owner field and the Apply nodes’ inputs fields, one can navigate a graph from an output all the way to the inputs. The opposite direction is not possible until an FunctionGraph has annotated the Variables with the clients field, ie, before the compilation process has begun a Variable does not know which Apply nodes take it as input.

Code Example

import theano
from theano import tensor

a = tensor.constant(1.5)        # declare a symbolic constant
b = tensor.fscalar()            # declare a symbolic floating-point scalar

c = a + b                       # create a simple expression

f = theano.function([b], [c])   # this works because a has a value associated with it already

assert 4.0 == f(2.5)            # bind 2.5 to an internal copy of b and evaluate an internal c

theano.function([a], [c])       # compilation error because b (required by c) is undefined

theano.function([a,b], [c])     # compilation error because a is constant, it can't be an input

d = tensor.value(1.5)           # create a value similar to the constant 'a'
e = d + b
theano.function([d,b], [e])     # this works.  d's default value of 1.5 is ignored.

The python variables a,b,c all refer to instances of type Variable. The Variable refered to by a is also an instance of Constant.

compile.function uses each Apply instance’s inputs attribute together with each Variable’s owner field to determine which inputs are necessary to compute the function’s outputs.

clone()

Return a new Variable like self.

Return type:Variable instance
Returns:a new Variable instance (or subclass instance) with no owner or index.
Note :tags are copied to the returned instance.
Note :name is copied to the returned instance.
eval(inputs_to_values=None)

Evaluates this variable.

inputs_to_values: a dictionary mapping theano Variables to values.

PureType.filter(data, strict=False, allow_downcast=None)

Required: Return data or an appropriately wrapped/converted data.

Subclass implementation should raise a TypeError exception if the data is not of an acceptable type.

If strict is True, the data returned must be the same as the data passed as an argument. If it is False, and allow_downcast is True, filter may cast it to an appropriate type. If allow_downcast is False, filter may only upcast it, not lose precision. If allow_downcast is None (default), the behaviour can be Type-dependent, but for now it means only Python floats can be downcasted, and only to floatX scalars.

Exceptions :
  • MethodNotDefined: subclass doesn’t implement this function.
PureType.filter_variable(other)

Convert a symbolic variable into this Type, if compatible.

For the moment, the only Types compatible with one another are TensorType and CudaNdarrayType, provided they have the same number of dimensions, same broadcasting pattern, and same dtype.

If Types are not compatible, a TypeError should be raised.

PureType.is_valid_value(a)

Required: Return True for any python object a that would be a legal value for a Variable of this Type

PureType.make_variable(name=None)

Return a new Variable instance of Type self.

Parameters :
  • name: None or str

    A pretty string for printing and debugging.

PureType.value_validity_msg(a)

Optional: return a message explaining the output of is_valid_value

PureType.values_eq(a, b)

Return True if a and b can be considered exactly equal.

a and b are assumed to be valid values of this Type.

PureType.values_eq_approx(a, b)

Return True if a and b can be considered approximately equal.

Parameters:
  • a – a potential value for a Variable of this Type.
  • b – a potential value for a Variable of this Type.
Return type:

Bool

This function is used by theano debugging tools to decide whether two values are equivalent, admitting a certain amount of numerical instability. For example, for floating-point numbers this function should be an approximate comparison.

By default, this does an exact comparison.

class theano.gof.type.SingletonType

Convenient Base class for a Type subclass with no attributes

It saves having to implement __eq__ and __hash__

class theano.gof.type.Type

Convenience wrapper combining PureType and CLinkerType.

Theano comes with several subclasses of such as:

  • Generic: for any python type
  • TensorType: for numpy.ndarray
  • SparseType: for scipy.sparse

But you are encouraged to write your own, as described in WRITEME.

The following following code illustrates the use of a Type instance, here tensor.fvector:

# Declare a symbolic floating-point vector using __call__
b = tensor.fvector()

# Create a second Variable with the same Type instance
c = tensor.fvector()

Whenever you create a symbolic variable in theano (technically, Variable) it will contain a reference to a Type instance. That reference is typically constant during the lifetime of the Variable. Many variables can refer to a single Type instance, as do b and c above. The Type instance defines the kind of value which might end up in that variable when executing a Function. In this sense, theano is like a strongly-typed language because the types are included in the graph before the values. In our example above, b is a Variable which is guaranteed to correspond to a numpy.ndarray of rank 1 when we try to do some computations with it.

Many Op instances will raise an exception if they are applied to inputs with incorrect types. Type references are also useful to do type-checking in pattern-based optimizations.