Table Of Contents

Previous topic

tensor – Types and Ops for Symbolic numpy

Next topic

nnet – Ops related to neural networks

This Page

Basic Tensor Functionality

Theano supports any kind of Python object, but its focus is support for symbolic matrix expressions. When you type,

>>> x = T.fmatrix()

the x is a TensorVariable instance. The T.fmatrix object itself is an instance of TensorType. Theano knows what type of variable x is because x.type points back to T.fmatrix.

This chapter explains the various ways of creating tensor variables, the attributes and methods of TensorVariable and TensorType, and various basic symbolic math and arithmetic that Theano supports for tensor variables.

Creation

Theano provides a list of predefined tensor types that can be used to create a tensor variables. Variables can be named to facilitate debugging, and all of these constructors accept an optional name argument. For example, the following each produce a TensorVariable instance that stands for a 0-dimensional ndarray of integers with the name 'myvar':

>>> x = scalar('myvar', dtype='int32')
>>> x = iscalar('myvar')
>>> x = TensorType(dtype='int32', broadcastable=())('myvar')

Constructors with optional dtype

These are the simplest and often-preferred methods for creating symbolic variables in your code. By default, they produce floating-point variables (with dtype determined by config.floatX, see floatX) so if you use these constructors it is easy to switch your code between different levels of floating-point precision.

tensor.scalar(name=None, dtype=config.floatX)

Return a Variable for a 0-dimensional ndarray

tensor.vector(name=None, dtype=config.floatX)

Return a Variable for a 1-dimensional ndarray

tensor.row(name=None, dtype=config.floatX)

Return a Variable for a 2-dimensional ndarray in which the number of rows is guaranteed to be 1.

tensor.col(name=None, dtype=config.floatX)

Return a Variable for a 2-dimensional ndarray in which the number of columns is guaranteed to be 1.

tensor.matrix(name=None, dtype=config.floatX)

Return a Variable for a 2-dimensional ndarray

tensor.tensor3(name=None, dtype=config.floatX)

Return a Variable for a 3-dimensional ndarray

tensor.tensor4(name=None, dtype=config.floatX)

Return a Variable for a 4-dimensional ndarray

All Fully-Typed Constructors

The following TensorType instances are provided in the theano.tensor module. They are all callable, and accept an optional name argument. So for example:

from theano.tensor import *

x = dmatrix()        # creates one Variable with no name
x = dmatrix('x')     # creates one Variable with name 'x'
xyz = dmatrix('xyz') # creates one Variable with name 'xyz'
Constructor dtype ndim shape broadcastable
bscalar int8 0 () ()
bvector int8 1 (?,) (False,)
brow int8 2 (1,?) (True, False)
bcol int8 2 (?,1) (False, True)
bmatrix int8 2 (?,?) (False, False)
btensor3 int8 3 (?,?,?) (False, False, False)
btensor4 int8 4 (?,?,?,?) (False, False, False, False)
wscalar int16 0 () ()
wvector int16 1 (?,) (False,)
wrow int16 2 (1,?) (True, False)
wcol int16 2 (?,1) (False, True)
wmatrix int16 2 (?,?) (False, False)
wtensor3 int16 3 (?,?,?) (False, False, False)
wtensor4 int16 4 (?,?,?,?) (False, False, False, False)
iscalar int32 0 () ()
ivector int32 1 (?,) (False,)
irow int32 2 (1,?) (True, False)
icol int32 2 (?,1) (False, True)
imatrix int32 2 (?,?) (False, False)
itensor3 int32 3 (?,?,?) (False, False, False)
itensor4 int32 4 (?,?,?,?) (False, False, False, False)
lscalar int64 0 () ()
lvector int64 1 (?,) (False,)
lrow int64 2 (1,?) (True, False)
lcol int64 2 (?,1) (False, True)
lmatrix int64 2 (?,?) (False, False)
ltensor3 int64 3 (?,?,?) (False, False, False)
ltensor4 int64 4 (?,?,?,?) (False, False, False, False)
dscalar float64 0 () ()
dvector float64 1 (?,) (False,)
drow float64 2 (1,?) (True, False)
dcol float64 2 (?,1) (False, True)
dmatrix float64 2 (?,?) (False, False)
dtensor3 float64 3 (?,?,?) (False, False, False)
dtensor4 float64 4 (?,?,?,?) (False, False, False, False)
fscalar float32 0 () ()
fvector float32 1 (?,) (False,)
frow float32 2 (1,?) (True, False)
fcol float32 2 (?,1) (False, True)
fmatrix float32 2 (?,?) (False, False)
ftensor3 float32 3 (?,?,?) (False, False, False)
ftensor4 float32 4 (?,?,?,?) (False, False, False, False)
cscalar complex64 0 () ()
cvector complex64 1 (?,) (False,)
crow complex64 2 (1,?) (True, False)
ccol complex64 2 (?,1) (False, True)
cmatrix complex64 2 (?,?) (False, False)
ctensor3 complex64 3 (?,?,?) (False, False, False)
ctensor4 complex64 4 (?,?,?,?) (False, False, False, False)
zscalar complex128 0 () ()
zvector complex128 1 (?,) (False,)
zrow complex128 2 (1,?) (True, False)
zcol complex128 2 (?,1) (False, True)
zmatrix complex128 2 (?,?) (False, False)
ztensor3 complex128 3 (?,?,?) (False, False, False)
ztensor4 complex128 4 (?,?,?,?) (False, False, False, False)

Plural Constructors

There are several constructors that can produce multiple variables at once. These are not frequently used in practice, but often used in tutorial examples to save space!

iscalars, lscalars, fscalars, dscalars

Return one or more scalar variables.

ivectors, lvectors, fvectors, dvectors

Return one or more vector variables.

irows, lrows, frows, drows

Return one or more row variables.

icols, lcols, fcols, dcols

Return one or more col variables.

imatrices, lmatrices, fmatrices, dmatrices

Return one or more matrix variables.

Each of these plural constructors accepts an integer or several strings. If an integer is provided, the method will return that many Variables and if strings are provided, it will create one Variable for each string, using the string as the Variable’s name. For example:

from theano.tensor import *

x, y, z = dmatrices(3) # creates three matrix Variables with no names
x, y, z = dmatrices('x', 'y', 'z') # creates three matrix Variables named 'x', 'y' and 'z'

Custom tensor types

If you would like to construct a tensor variable with a non-standard broadcasting pattern, or a larger number of dimensions you’ll need to create your own TensorType instance. You create such an instance by passing the dtype and broadcasting pattern to the constructor. For example, you can create your own 5-dimensional tensor type

>>> dtensor5 = TensorType('float64', (False,)*5)
>>> x = dtensor5()
>>> z = dtensor5('z')

You can also redefine some of the provided types and they will interact correctly:

>>> my_dmatrix = TensorType('float64', (False,)*2)
>>> x = my_dmatrix()       # allocate a matrix variable
>>> my_dmatrix == dmatrix  # this compares True

See TensorType for more information about creating new types of Tensor.

Converting from Python Objects

Another way of creating a TensorVariable (a TensorSharedVariable to be precise) is by calling shared()

x = shared(numpy.random.randn(3,4))

This will return a shared variable whose .value is a numpy ndarray. The number of dimensions and dtype of the Variable are inferred from the ndarray argument. The argument to shared will not be copied, and subsequent changes will be reflected in x.value.

For additional information, see the shared() documentation.

Finally, when you use a numpy ndarry or a Python number together with TensorVariable instances in arithmetic expressions, the result is a TensorVariable. What happens to the ndarray or the number? Theano requires that the inputs to all expressions be Variable instances, so Theano automatically wraps them in a TensorConstant.

Note

Theano makes a copy of any ndarray that you use in an expression, so subsequent changes to that ndarray will not have any effect on the Theano expression.

For numpy ndarrays the dtype is given, but the broadcastable pattern must be inferred. The TensorConstant is given a type with a matching dtype, and a broadcastable pattern with a True for every shape dimension that is 1.

For python numbers, the broadcastable pattern is () but the dtype must be inferred. Python integers are stored in the smallest dtype that can hold them, so small constants like 1 are stored in a bscalar. Likewise, Python floats are stored in an fscalar if fscalar suffices to hold them perfectly, but a dscalar otherwise.

Note

When config.floatX==float32 (see config), then Python floats are stored instead as single-precision floats.

For fine control of this rounding policy, see theano.tensor.basic.autocast_float.

tensor.as_tensor_variable(x, name=None, ndim=None)

Turn an argument x into a TensorVariable or TensorConstant.

Many tensor Ops run their arguments through this function as pre-processing. It passes through TensorVariable instances, and tries to wrap other objects into TensorConstant.

When x is a Python number, the dtype is inferred as described above.

When x is a list or tuple it is passed through numpy.asarray

If the ndim argument is not None, it must be an integer and the output will be broadcasted if necessary in order to have this many dimensions.

Return type:TensorVariable or TensorConstant

TensorType and TensorVariable

class tensor.TensorType(Type)

The Type class used to mark Variables that stand for numpy.ndarray values (numpy.memmap, which is a subclass of numpy.ndarray, is also allowed). Recalling to the tutorial, the purple box in the tutorial’s graph-structure figure is an instance of this class.

broadcastable

A tuple of True/False values, one for each dimension. True in position ‘i’ indicates that at evaluation-time, the ndarray will have size 1 in that ‘i’-th dimension. Such a dimension is called a broadcastable dimension (see Broadcasting in Theano vs. Numpy).

The broadcastable pattern indicates both the number of dimensions and whether a particular dimension must have length 1.

Here is a table mapping some broadcastable patterns to what they mean:

pattern interpretation
[] scalar
[True] 1D scalar (vector of length 1)
[True, True] 2D scalar (1x1 matrix)
[False] vector
[False, False] matrix
[False] * n nD tensor
[True, False] row (1xN matrix)
[False, True] column (Mx1 matrix)
[False, True, False] A Mx1xP tensor (a)
[True, False, False] A 1xNxP tensor (b)
[False, False, False] A MxNxP tensor (pattern of a + b)

For dimensions in which broadcasting is False, the length of this dimension can be 1 or more. For dimensions in which broadcasting is True, the length of this dimension must be 1.

When two arguments to an element-wise operation (like addition or subtraction) have a different number of dimensions, the broadcastable pattern is expanded to the left, by padding with True. For example, a vector’s pattern, [False], could be expanded to [True, False], and would behave like a row (1xN matrix). In the same way, a matrix ([False, False]) would behave like a 1xNxP tensor ([True, False, False]).

If we wanted to create a type representing a matrix that would broadcast over the middle dimension of a 3-dimensional tensor when adding them together, we would define it like this:

>>> middle_broadcaster = TensorType('complex64', [False, True, False])
ndim

The number of dimensions that a Variable’s value will have at evaluation-time. This must be known when we are building the expression graph.

dtype

A string indicating the numerical type of the ndarray for which a Variable of this Type is standing.

The dtype attribute of a TensorType instance can be any of the following strings.

dtype domain bits
'int8' signed integer 8
'int16' signed integer 16
'int32' signed integer 32
'int64' signed integer 64
'uint8' unsigned integer 8
'uint16' unsigned integer 16
'uint32' unsigned integer 32
'uint64' unsigned integer 64
'float32' floating point 32
'float64' floating point 64
'complex64' complex 64 (two float32)
'complex128' complex 128 (two float64)
__init__(self, dtype, broadcastable)

If you wish to use a type of tensor which is not already available (for example, a 5D tensor) you can build an appropriate type by instantiating TensorType.

TensorVariable

class tensor.TensorVariable(Variable, _tensor_py_operators)

The result of symbolic operations typically have this type.

See _tensor_py_operators for most of the attributes and methods you’ll want to call.

class tensor.TensorConstant(Variable, _tensor_py_operators)

Python and numpy numbers are wrapped in this type.

See _tensor_py_operators for most of the attributes and methods you’ll want to call.

class tensor.TensorSharedVariable(Variable, _tensor_py_operators)

This type is returned by shared() when the value to share is a numpy ndarray.

See _tensor_py_operators for most of the attributes and methods you’ll want to call.

class tensor._tensor_py_operators(object)

This mix-in class adds convenient attributes, methods, and support for Python operators (see Operator Support).

type

A reference to the TensorType instance describing the sort of values that might be associated with this variable.

ndim

The number of dimensions of this tensor. Aliased to TensorType.ndim.

dtype

The numeric type of this tensor. Aliased to TensorType.dtype.

reshape(shape, ndim=None)

Returns a view of this tensor that has been reshaped as in numpy.reshape. If the shape is a Variable argument, then you might need to use the optional ndim parameter to declare how many elements the shape has, and therefore how many dimensions the reshaped Variable will have.

See reshape().

dimshuffle(*pattern)

Returns a view of this tensor with permuted dimensions. Typically the pattern will include the integers 0, 1, ... ndim-1, and any number of ‘x’ characters in dimensions where this tensor should be broadcasted.

A few examples of patterns and their effect:

  • (‘x’) -> make a 0d (scalar) into a 1d vector
  • (0, 1) -> identity for 2d vectors
  • (1, 0) -> inverts the first and second dimensions
  • (‘x’, 0) -> make a row out of a 1d vector (N to 1xN)
  • (0, ‘x’) -> make a column out of a 1d vector (N to Nx1)
  • (2, 0, 1) -> AxBxC to CxAxB
  • (0, ‘x’, 1) -> AxB to Ax1xB
  • (1, ‘x’, 0) -> AxB to Bx1xA
flatten(ndim=1)

Returns a view of this tensor with ndim dimensions, whose shape for the first ndim-1 dimensions will be the same as self, and shape in the remaining dimension will be expanded to fit in all the data from self.

See flatten().

T

Transpose of this tensor.

>>> x = T.zmatrix()
>>> y = 3+.2j * x.T

Note

In numpy and in Theano, the transpose of a vector is exactly the same vector! Use reshape or dimshuffle to turn your vector into a row or column matrix.

Shaping and Shuffling

To re-order the dimensions of a variable, to insert or remove broadcastable dimensions, see _tensor_py_operators.dimshuffle().

tensor.shape(x)

Returns an lvector representing the shape of x.

tensor.reshape(x, newshape, ndim=None)
Parameters:
  • x (any TensorVariable (or compatible)) – variable to be reshaped
  • newshape (lvector (or compatible)) – the new shape for x
  • ndim – optional - the length that newshape‘s value will have. If this is None, then reshape() will infer it from newshape.
Return type:

variable with x’s dtype, but ndim dimensions

Note

This function can infer the length of a symbolic newshape in some cases, but if it cannot and you do not provide the ndim, then this function will raise an Exception.

tensor.shape_padleft(x, n_ones=1)

Reshape x by left padding the shape with n_ones 1s. Note that all this new dimension will be broadcastable. To make them non-broadcastable see the unbroadcast().

Parameters:x (any TensorVariable (or compatible)) – variable to be reshaped
tensor.shape_padright(x, n_ones=1)

Reshape x by right padding the shape with n_ones 1s. Note that all this new dimension will be broadcastable. To make them non-broadcastable see the unbroadcast().

Parameters:x (any TensorVariable (or compatible)) – variable to be reshaped
tensor.unbroadcast(x, *axes)

Make x impossible to broadcast in the specified axes axes. For example, unbroadcast(x,0) will make the first dimension of x unbroadcastable.

tensor.addbroadcast(x, *axes)

Make x broadcastable in the specified axes axes. For example, unbroadcast(x,0) will make the first dimension of x broadcastable. When performing the function, if the length of x along that dimension is not 1, a ValueError will be raised.

tensor.flatten(x, outdim=1)

Similar to reshape(), but the shape is inferred from the shape of x.

Parameters:
  • x (any TensorVariable (or compatible)) – variable to be flattened
  • outdim (int) – the number of dimensions in the returned variable
Return type:

variable with same dtype as x and outdim dimensions

Returns:

variable with the same shape as x in the leading outdim-1 dimensions, but with all remaining dimensions of x collapsed into the last dimension.

For example, if we flatten a tensor of shape (2,3,4,5) with flatten(x, outdim=2), then we’ll have the same (2-1=1) leading dimensions (2,), and the remaining dimensions are collapsed. So the output in this example would have shape (2, 60).

tensor.zeros_like(x)
Parameters:x – tensor that has same shape as output

Returns a tensor filled with 0s that has same shape as x.

tensor.ones_like(x)
Parameters:x – tensor that has same shape as output

Returns a tensor filled with 1s that has same shape as x.

tensor.fill(a, b)
Parameters:
  • a – tensor that has same shape as output
  • b – theano scalar or value with which you want to fill the output

Create a matrix by filling the shape of a with b

tensor.eye(n, m=None, k=0, dtype=theano.config.floatX)
Parameters:
  • n – number of rows in output (value or theano scalar)
  • m – number of columns in output (value or theano scalar)
  • k – Index of the diagonal: 0 refers to the main diagonal, a positive value refers to an upper diagonal, and a negative value to a lower diagonal. It can be a theano scalar.
Returns:

An array where all elements are equal to zero, except for the k-th diagonal, whose values are equal to one.

tensor.identity_like(x)
Parameters:x – tensor
Returns:A tensor of same shape as x that is filled with 0s everywhere except for the main diagonal, whose values are equal to one. The output will have same dtype as x.
tensor.stack(*tensors)

Return a Tensor representing for the arguments all stacked up into a single Tensor. (of 1 rank greater).

Parameters:tensors – one or more tensors of the same rank
Returns:A tensor such that rval[0] == tensors[0], rval[1] == tensors[1], etc.
>>> x0 = T.scalar()
>>> x1 = T.scalar()
>>> x2 = T.scalar()
>>> x = T.stack(x0, x1, x2)
>>> # x.ndim == 1, is a vector of length 3.
tensor.concatenate(tensor_list, axis=0)
Parameters:
  • tensor_list (a list or tuple of Tensors that all have the same shape in the axes not specified by the axis argument.) – one or more Tensors to be concatenated together into one.
  • axis (literal or symbolic integer) – Tensors will be joined along this axis, so they may have different shape[axis]
>>> x0 = T.fmatrix()
>>> x1 = T.ftensor3()
>>> x2 = T.fvector()
>>> x = T.concatenate([x0, x1[0], T.shape_padright(x2)], axis=1)
>>> # x.ndim == 2

Reductions

tensor.max(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the sum
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :maximum of x along axis
axis can be:
  • None - in which case the maximum is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.argmax(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis along which to compute the maximum
Parameter :keepdims - (boolean) If this is set to True, the axis which is reduced is left in the result as a dimension with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :the index of the maximum value along a given axis
if axis=None, Theano 0.5rc1 or later: argmax over the flattened tensor (like numpy)
older: then axis is assumed to be ndim(x)-1
tensor.max_and_argmax(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis along which to compute the maximum
Parameter :keepdims - (boolean) If this is set to True, the axis which is reduced is left in the result as a dimension with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :the maxium value along a given axis and its index.
if axis=None, Theano 0.5rc1 or later: max_and_argmax over the flattened tensor (like numpy)
older: then axis is assumed to be ndim(x)-1
tensor.min(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the sum
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :minimum of x along axis
axis can be:
  • None - in which case the minimum is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.argmin(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis along which to compute the minimum
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :the index of the minimum value along a given axis
if axis=None, Theano 0.5rc1 or later: argmin over the flattened tensor (like numpy)
older: then axis is assumed to be ndim(x)-1
tensor.sum(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the sum
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :sum of x along axis
axis can be:
  • None - in which case the sum is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.prod(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the product
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :product of every term in x along axis
axis can be:
  • None - in which case the sum is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.mean(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the mean
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :mean value of x along axis
axis can be:
  • None - in which case the mean is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.var(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the variance
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :variance of x along axis
axis can be:
  • None - in which case the variance is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.std(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to compute the standard deviation
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :variance of x along axis
axis can be:
  • None - in which case the standard deviation is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.all(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to apply ‘bitwise and’
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :bitwise and of x along axis
axis can be:
  • None - in which case the ‘bitwise and’ is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes
tensor.any(x, axis=None, keepdims=False)
Parameter :x - symbolic Tensor (or compatible)
Parameter :axis - axis or axes along which to apply bitwise or
Parameter :keepdims - (boolean) If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the original tensor.
Returns :bitwise or of x along axis
axis can be:
  • None - in which case the ‘bitwise or’ is computed along all axes (like numpy)
  • an int - computed along this axis
  • a list of ints - computed along these axes

Indexing

Like numpy, Theano distinguishes between basic and advanced indexing. Theano fully supports basic indexing (see numpy’s basic indexing).

Advanced indexing is almost entirely unsupported (for now). The one sort of advanced indexing that is supported is the retrieval of the c[i]’th element of each row of a matrix x:

>>> x = T.fmatrix()
>>> c = T.lvector()
>>> x[T.arange(c.shape[0]), c]

Index-assignment is not supported. If you want to do something like a[5] = b or a[5]+=b, see set_subtensor() and inc_subtensor() below.

Operator Support

Many Python operators are supported.

>>> a, b = T.itensor3(), T.itensor3() # example inputs

Arithmetic

>>> a + 3      # T.add(a, 3) -> itensor3
>>> 3 - a      # T.sub(3, a)
>>> a * 3.5    # T.mul(a, 3.5) -> ftensor3 or dtensor3 (depending on casting)
>>> 2.2 / a    # T.truediv(2.2, a)
>>> 2.2 // a   # T.intdiv(2.2, a)
>>> 2.2**a     # T.pow(2.2, a)
>>> b % a      # T.mod(b, a)

Bitwise

>>> a & b      # T.and_(a,b)    bitwise and (alias T.bitwise_and)
>>> a ^ 1      # T.xor(a,1)     bitwise xor (alias T.bitwise_xor)
>>> a | b      # T.or_(a,b)     bitwise or (alias T.bitwise_or)
>>> ~a         # T.invert(a)    bitwise invert (alias T.bitwise_not)

Inplace

In-place operators are not supported. Theano’s graph-optimizations will determine which intermediate values to use for in-place computations. If you would like to update the value of a shared variable, consider using the updates argument to theano.function().

Elementwise

Casting

tensor.cast(x, dtype)

Cast any tensor x to a Tensor of the same shape, but with a different numerical type dtype.

This is not a reinterpret cast, but a coersion cast, similar to numpy.asarray(x, dtype=dtype).

import theano.tensor as T
x_as_float = T.matrix()
x_as_int = T.cast(x, 'int32')

Attempting to casting a complex value to a real value is ambiguous and will raise an exception. Use real(), imag(), abs(), or angle().

tensor.real(x)

Return the real (not imaginary) components of Tensor x. For non-complex x this function returns x.

tensor.imag(x)

Return the imaginary components of Tensor x. For non-complex x this function returns zeros_like(x).

Comparisons

The six usual equality and inequality operators share the same interface.
Parameter:a - symbolic Tensor (or compatible)
Parameter:b - symbolic Tensor (or compatible)
Return type:symbolic Tensor
Returns:a symbolic tensor representing the application of the logical elementwise operator.

Note

Theano has no boolean dtype. Instead, all boolean tensors are represented in 'int8'.

Here is an example with the less-than operator.

import theano.tensor as T
x,y = T.dmatrices('x','y')
z = T.le(x,y)
tensor.lt(a, b)

Returns a symbolic 'int8' tensor representing the result of logical less-than (a<b).

Also available using syntax a < b

tensor.gt(a, b)

Returns a symbolic 'int8' tensor representing the result of logical greater-than (a>b).

Also available using syntax a > b

tensor.le(a, b)

Returns a variable representing the result of logical less than or equal (a<=b).

Also available using syntax a <= b

tensor.ge(a, b)

Returns a variable representing the result of logical greater or equal than (a>=b).

Also available using syntax a >= b

tensor.eq(a, b)

Returns a variable representing the result of logical equality (a==b).

tensor.neq(a, b)

Returns a variable representing the result of logical inequality (a!=b).

Condition

tensor.switch(cond, ift, iff)
Returns a variable representing a switch between ift (iftrue) and iff (iffalse)

based on the condition cond. This is the theano equivalent of numpy.where.

Parameter:cond - symbolic Tensor (or compatible)
Parameter:ift - symbolic Tensor (or compatible)
Parameter:iff - symbolic Tensor (or compatible)
Return type:symbolic Tensor
import theano.tensor as T
a,b = T.dmatrices('a','b')
x,y = T.dmatrices('x','y')
z = T.switch(T.lt(a,b), x, y)
tensor.where(cond, ift, iff)

Alias for switch. where is the numpy name.

tensor.clip(x, min, max)

Return a variable representing x, but with all elements greater than max clipped to max and all elements less than min clipped to min.

Normal broadcasting rules apply to each of x, min, and max.

Bit-wise

The bitwise operators possess this interface:
Parameter:a - symbolic Tensor of integer type.
Parameter:b - symbolic Tensor of integer type.

Note

The bitwise operators must have an integer type as input.

The bit-wise not (invert) takes only one parameter.

Return type:symbolic Tensor with corresponding dtype.
tensor.and_(a, b)

Returns a variable representing the result of the bitwise and.

tensor.or_(a, b)

Returns a variable representing the result of the bitwise or.

tensor.xor(a, b)

Returns a variable representing the result of the bitwise xor.

tensor.invert(a)

Returns a variable representing the result of the bitwise not.

tensor.bitwise_and(a, b)

Alias for and_. bitwise_and is the numpy name.

tensor.bitwise_or(a, b)

Alias for or_. bitwise_or is the numpy name.

tensor.bitwise_xor(a, b)

Alias for xor_. bitwise_xor is the numpy name.

tensor.bitwise_not(a, b)

Alias for invert. invert is the numpy name.

Here is an example using the bit-wise and_ via the & operator:

import theano.tensor as T
x,y = T.imatrices('x','y')
z = x & y

Mathematical

tensor.abs_(a)

Returns a variable representingthe absolute of a, ie |a|.

Note

Can also be accessed with abs(a).

tensor.angle(a)

Returns a variable representing angular component of complex-valued Tensor a.

tensor.exp(a)

Returns a variable representing the exponential of a, ie e^a.

tensor.maximum(a, b)

Returns a variable representing the maximum element by element of a and b

tensor.minimum(a, b)

Returns a variable representing the minimum element by element of a and b

tensor.neg(a)

Returns a variable representing the negation of a (also -a).

tensor.inv(a)

Returns a variable representing the inverse of a, ie 1.0/a. Also called reciprocal.

tensor.log(a), log2(a), log10(a)

Returns a variable representing the base e, 2 or 10 logarithm of a.

tensor.sgn(a)

Returns a variable representing the sign of a.

tensor.ceil(a)

Returns a variable representing the ceiling of a (for example ceil(2.1) is 3).

tensor.floor(a)

Returns a variable representing the floor of a (for example floor(2.9) is 2).

tensor.round(a, mode="half_away_from_zero")

Returns a variable representing the rounding of a in the same dtype as a. Implemented rounding mode are half_away_from_zero and half_to_even.

tensor.iround(a, mode="half_away_from_zero")

Short hand for cast(round(a, mode),’int64’).

tensor.sqr(a)

Returns a variable representing the square of a, ie a^2.

tensor.sqrt(a)

Returns a variable representing the of a, ie a^0.5.

tensor.cos(a), sin(a), tan(a)

Returns a variable representing the trigonometric functions of a (cosine, sine and tangent).

tensor.cosh(a), sinh(a), tanh(a)

Returns a variable representing the hyperbolic trigonometric functions of a (hyperbolic cosine, sine and tangent).

tensor.erf(a), erfc(a)

Returns a variable representing the error function or the complementary error function. wikipedia

tensor.erfinv(a), erfcinv(a)

Returns a variable representing the inverse error function or the inverse complementary error function. wikipedia

Broadcasting in Theano vs. Numpy

Broadcasting is a mechanism which allows tensors with different numbers of dimensions to be added or multiplied together by (virtually) replicating the smaller tensor along the dimensions that it is lacking.

Broadcasting is the mechanism by which a scalar may be added to a matrix, a vector to a matrix or a scalar to a vector.

../../_images/bcast.png

Broadcasting a row matrix. T and F respectively stand for True and False and indicate along which dimensions we allow broadcasting.

If the second argument were a vector, its shape would be (2,) and its broadcastable pattern (F,). They would be automatically expanded to the left to match the dimensions of the matrix (adding 1 to the shape and T to the pattern), resulting in (1, 2) and (T, F). It would then behave just like the example above.

Unlike numpy which does broadcasting dynamically, Theano needs to know, for any operation which supports broadcasting, which dimensions will need to be broadcasted. When applicable, this information is given in the Type of a Variable.

See also:

Linear Algebra

tensor.dot(X, Y)
Parameters:
  • X (symbolic matrix or vector) – left term
  • Y (symbolic matrix or vector) – right term
Return type:

symbolic matrix or vector

Returns:

the inner product of X and Y.

tensor.outer(X, Y)
Parameters:
  • X (symbolic vector) – left term
  • Y (symbolic vector) – right term
Return type:

symbolic matrix

Returns:

vector-vector outer product

tensor.tensordot(a, b, axes=2)

Given two tensors a and b,tensordot computes a generalized dot product over the provided axes. Theano’s implementation reduces all expressions to matrix or vector dot products and is based on code from Tijmen Tieleman’s gnumpy (http://www.cs.toronto.edu/~tijmen/gnumpy.html).

Parameters:
  • a (symbolic tensor) – the first tensor variable
  • b (symbolic tensor) – the second tensor variable
  • axes (int or array-like of length 2) –

    an integer or array. If an integer, the number of axes to sum over. If an array, it must have two array elements containing the axes to sum over in each tensor.

    Note that the default value of 2 is not guaranteed to work for all values of a and b, and an error will be raised if that is the case. The reason for keeping the default is to maintain the same signature as numpy’s tensordot function (and np.tensordot raises analogous errors for non-compatible inputs).

    If an integer i, it is converted to an array containing the last i dimensions of the first tensor and the first i dimensions of the second tensor:

    axes = [range(a.ndim - i, b.ndim), range(i)]

    If an array, its two elements must contain compatible axes of the two tensors. For example, [[1, 2], [2, 0]] means sum over the 2nd and 3rd axes of a and the 3rd and 1st axes of b. (Remember axes are zero-indexed!) The 2nd axis of a and the 3rd axis of b must have the same shape; the same is true for the 3rd axis of a and the 1st axis of b.

Returns:

a tensor with shape equal to the concatenation of a’s shape (less any dimensions that were summed over) and b’s shape (less any dimensions that were summed over).

Return type:

symbolic tensor

It may be helpful to consider an example to see what tensordot does. Theano’s implementation is identical to NumPy’s. Here a has shape (2, 3, 4) and b has shape (5, 6, 4, 3). The axes to sum over are [[1, 2], [3, 2]] – note that a.shape[1] == b.shape[3] and a.shape[2] == b.shape[2]; these axes are compatible. The resulting tensor will have shape (2, 5, 6) – the dimensions that are not being summed:

a = np.random.random((2,3,4))
b = np.random.random((5,6,4,3))

#tensordot
c = np.tensordot(a, b, [[1,2],[3,2]])

#loop replicating tensordot
a0, a1, a2 = a.shape
b0, b1, _, _ = b.shape
cloop = np.zeros((a0,b0,b1))

#loop over non-summed indices -- these exist
#in the tensor product.
for i in range(a0):
    for j in range(b0):
        for k in range(b1):
            #loop over summed indices -- these don't exist
            #in the tensor product.
            for l in range(a1):
                for m in range(a2):
                    cloop[i,j,k] += a[i,l,m] * b[j,k,m,l]

np.allclose(c, cloop) #true

This specific implementation avoids a loop by transposing a and b such that the summed axes of a are last and the summed axes of b are first. The resulting arrays are reshaped to 2 dimensions (or left as vectors, if appropriate) and a matrix or vector dot product is taken. The result is reshaped back to the required output dimensions.

In an extreme case, no axes may be specified. The resulting tensor will have shape equal to the concatenation of the shapes of a and b:

c = np.tensordot(a, b, 0)
print(a.shape) #(2,3,4)
print(b.shape) #(5,6,4,3)
print(c.shape) #(2,3,4,5,6,4,3)

See the documentation of numpy.tensordot for more examples.

tensor.batched_dot(X, Y)
Parameters:
  • x – A Tensor with sizes e.g.: for 3D (dim1, dim3, dim2)
  • y – A Tensor with sizes e.g.: for 3D (dim1, dim2, dim4)

This function computes the dot product between the two tensors, by iterating over the first dimension using scan. Returns a tensor of size e.g. if it is 3D: (dim1, dim3, dim4) Example: >>> first = T.tensor3(‘first’) >>> second = T.tensor3(‘second’) >>> result = batched_dot(first, second)

Note :

This is a subset of numpy.einsum, but we do not provide it for now. But numpy einsum is slower than dot or tensordot: http://mail.scipy.org/pipermail/numpy-discussion/2012-October/064259.html

Parameters:
  • X (symbolic tensor) – left term
  • Y (symbolic tensor) – right term
Returns:

tensor of products

Gradient / Differentiation

tensor.grad(cost, wrt, g_cost=None, consider_constant=None, warn_type=False)

Return symbolic gradients for one or more variables with respect to some cost.

For more information about how automatic differentiation works in Theano, see gradient. For information on how to implement the gradient of a certain Op, see grad().

Parameters:
  • cost (0-d tensor variable) – a scalar with respect to which we are differentiating
  • wrt (tensor variable or list of tensor variables) – term[s] for which we want gradients
  • g_cost (same as type of cost) – the gradient on the cost
  • consider_constant (list of variables) – variables whose gradients will be held at 0.
  • warn_type (bool) – True will trigger warnings via the logging module when the gradient on an expression has a different type than the original expression
Return type:

variable or list of variables (matching wrt)

Returns:

gradients of the cost with respect to each of the wrt terms

List of Implemented R op

See the gradient tutorial for the R op documentation.

list of ops that support R-op:
  • with test [Most is tensor/tests/test_rop.py]
    • SpecifyShape
    • MaxAndArgmax
    • Subtensor
    • IncSubtensor set_subtensor too
    • Alloc
    • Dot
    • Elemwise
    • Sum
    • Softmax
    • Shape
    • Join
    • Rebroadcast
    • Reshape
    • Flatten
    • DimShuffle
    • Scan [In scan_module/tests/test_scan.test_rop]
  • without test
    • Split
    • ARange
    • ScalarFromTensor
    • AdvancedSubtensor1
    • AdvancedIncSubtensor1
    • AdvancedIncSubtensor

Partial list of ops without support for R-op:

  • All sparse ops
  • All linear algebra ops.
  • PermuteRowElements
  • Tile
  • AdvancedSubtensor
  • TensorDot
  • Outer
  • Prod
  • MulwithoutZeros
  • ProdWithoutZeros
  • CAReduce(for max,... done for MaxAndArgmax op)
  • MaxAndArgmax(only for matrix on axis 0 or 1)