Note
TODO Freshen up this old documentation
io - defines theano.function [TODO]
Inputs
The inputs
argument to theano.function
is a list, containing the Variable
instances for which values will be specified at the time of the function call. But inputs can be more than just Variables.In
instances let us attach properties to Variables
to tell function more about how to use them.
- class
theano.compile.io.
In
(object)[source] init
(variable, name=None, value=None, update=None, mutable=False, strict=False, autoname=True, implicit=None)[source]variable
: a Variable instance. This will be assigned a valuebefore running the function, not computed from its owner.
name
: Any type. (If autoname_input==True
, defaults tovariable.name
). If name
is a valid Python identifier, this inputcan be set by kwarg
, and its value can be accessed byself.<name>
. The default value is None
.
- <code>value</code>: literal or <code>Container</code>. The initial/default value for this
- input. If update is`` None``, this input acts just likean argument with a default value in Python. If update is not <code>None</code>,changes to thisvalue will “stick around”, whether due to an update or a user’sexplicit action.
update
: Variable instance. This expression Variable willreplace value
after each function call. The default value isNone
, indicating that no update is to be done.
mutable
: Bool (requires value). If True
, permit thecompiled function to modify the Python object being used as thedefault value. The default value is False
.
strict
: Bool (default: False
). True
means that the valueyou pass for this input must have exactly the right type. Otherwise, itmay be cast automatically to the proper type.
autoname
: Bool. If set to True
, if name
is None
andthe Variable has a name, it will be taken as the input’sname. If autoname is set to False
, the name is the exactvalue passed as the name parameter (possibly None
).
- <code>implicit</code>: Bool or <code>None</code> (default: <code>None</code>)
-
True
: This input is implicit in the sense that the user is not allowedto provide a value for it. Requires value
to be set.
False
: The user can provide a value for this input. Be carefulwhen value
is a container, because providing an input value willoverwrite the content of this container.
None
: Automatically choose between True
or False
depending on thesituation. It will be set to False
in all cases except ifvalue
is a container (so that there is less risk of accidentallyoverwriting its content without being aware of it).
Value: initial and default values
A non-None value argument makes an In() instance an optional parameterof the compiled function. For example, in the following code we aredefining an arity-2 function inc
.
- >>> import theano.tensor as T
- >>> from theano import function
- >>> from theano.compile.io import In
- >>> u, x, s = T.scalars('u', 'x', 's')
- >>> inc = function([u, In(x, value=3), In(s, update=(s+x*u), value=10.0)], [])
Since we provided a value
for s
and x
, we can call it with just a value for u
like this:
- >>> inc(5) # update s with 10+3*5
- []
- >>> print(inc[s])
- 25.0
The effect of this call is to increment the storage associated to s
in inc
by 15.
If we pass two arguments to inc
, then we override the value associated tox
, but only for this one function call.
- >>> inc(3, 4) # update s with 25 + 3*4
- []
- >>> print(inc[s])
- 37.0
- >>> print(inc[x]) # the override value of 4 was only temporary
- 3.0
If we pass three arguments to inc
, then we override the value associatedwith x
and u
and s
.Since s
‘s value is updated on every call, the old value of s
will be ignored and then replaced.
- >>> inc(3, 4, 7) # update s with 7 + 3*4
- []
- >>> print(inc[s])
- 19.0
We can also assign to inc[s]
directly:
- >>> inc[s] = 10
- >>> inc[s]
- array(10.0)
Input Argument Restrictions
The following restrictions apply to the inputs to theano.function
:
- Every input list element must be a valid
In
instance, or must beupgradable to a validIn
instance. See the shortcut rules below. - The same restrictions apply as in Python function definitions:default arguments and keyword arguments must come at the end ofthe list. Un-named mandatory arguments must come at the beginning ofthe list.
- Names have to be unique within an input list. If multiple inputshave the same name, then the function will raise an exception. [*Whichexception?]
- Two
In
instances may not name the same Variable. I.e. you cannotgive the same parameter multiple times.
If no name is specified explicitly for an In instance, then its namewill be taken from the Variable’s name. Note that this feature can causeharmless-looking input lists to not satisfy the two conditions above.In such cases, Inputs should be named explicitly to avoid problemssuch as duplicate names, and named arguments preceding unnamed ones.This automatic naming feature can be disabled by instantiating an Ininstance explicitly with the autoname
flag set to False.
Access to function values and containers
For each input, theano.function
will create a Container
ifvalue
was not already a Container
(or if implicit
was False
). At the time of a function call,each of these containers must be filled with a value. Each input (butespecially ones with a default value or an update expression) may have avalue between calls. The function interface defines a way to get atboth the current value associated with an input, as well as the containerwhich will contain all future values:
- The
value
property accesses the current values. It is both readable and writable, but assignments (writes) may be implemented by an internal copy and/or casts.- The
container
property accesses the corresponding container. This property accesses is a read-only dictionary-like interface. It is useful for fetching the container associated with a particular input to share containers between functions, or to have a sort of pointer to an always up-to-date value.
Both value
and container
properties provide dictionary-like access based on three types of keys:
- integer keys: you can look up a value/container by its position in the input list;
- name keys: you can look up a value/container by its name;
- Variable keys: you can look up a value/container by the Variable it corresponds to.
In addition to these access mechanisms, there is an even more convenientmethod to access values by indexing a Function directly by typingfn[<name>]
, as in the examples above.
To show some examples of these access methods…
- >>> from theano import tensor as T, function
- >>> a, b, c = T.scalars('xys') # set the internal names of graph nodes
- >>> # Note that the name of c is 's', not 'c'!
- >>> fn = function([a, b, ((c, c+a+b), 10.0)], [])
- >>> # the value associated with c is accessible in 3 ways
- >>> fn['s'] is fn.value[c]
- True
- >>> fn['s'] is fn.container[c].value
- True
- >>> fn['s']
- array(10.0)
- >>> fn(1, 2)
- []
- >>> fn['s']
- array(13.0)
- >>> fn['s'] = 99.0
- >>> fn(1, 0)
- []
- >>> fn['s']
- array(100.0)
- >>> fn.value[c] = 99.0
- >>> fn(1,0)
- []
- >>> fn['s']
- array(100.0)
- >>> fn['s'] == fn.value[c]
- True
- >>> fn['s'] == fn.container[c].value
- True
Input Shortcuts
Every element of the inputs list will be upgraded to an In instance if necessary.
- a Variable instance
r
will be upgraded likeIn(r)
- a tuple
(name, r)
will beIn(r, name=name)
- a tuple
(r, val)
will beIn(r, value=value, autoname=True)
- a tuple
((r,up), val)
will beIn(r, value=value, update=up, autoname=True)
- a tuple
(name, r, val)
will beIn(r, name=name, value=value)
- a tuple
(name, (r,up), val)
will beIn(r, name=name, value=val, update=up, autoname=True)
Example:
- >>> import theano
- >>> from theano import tensor as T
- >>> from theano.compile.io import In
- >>> x = T.scalar()
- >>> y = T.scalar('y')
- >>> z = T.scalar('z')
- >>> w = T.scalar('w')
- >>> fn = theano.function(inputs=[x, y, In(z, value=42), ((w, w+x), 0)],
- ... outputs=x + y + z)
- >>> # the first two arguments are required and the last two are
- >>> # optional and initialized to 42 and 0, respectively.
- >>> # The last argument, w, is updated with w + x each time the
- >>> # function is called.
- >>> fn(1) # illegal because there are two required arguments
- Traceback (most recent call last):
- ...
- TypeError: Missing required input: y
- >>> fn(1, 2) # legal, z is 42, w goes 0 -> 1 (because w <- w + x)
- array(45.0)
- >>> fn(1, y=2) # legal, z is 42, w goes 1 -> 2
- array(45.0)
- >>> fn(x=1, y=2) # illegal because x was not named
- Traceback (most recent call last):
- ...
- TypeError: Unknown input or state: x. The function has 3 named inputs (y, z, w), and 1 unnamed input which thus cannot be accessed through keyword argument (use 'name=...' in a variable's constructor to give it a name).
- >>> fn(1, 2, 3) # legal, z is 3, w goes 2 -> 3
- array(6.0)
- >>> fn(1, z=3, y=2) # legal, z is 3, w goes 3 -> 4
- array(6.0)
- >>> fn(1, 2, w=400) # legal, z is 42 again, w goes 400 -> 401
- array(45.0)
- >>> fn(1, 2) # legal, z is 42, w goes 401 -> 402
- array(45.0)
In the example above, z
has value 42 when no value is explicitly given.This default value is potentially used at every function invocation, becausez
has no update
or storage associated with it.
Outputs
The outputs
argument to function can be one of
None
, or- a Variable or
Out
instance, or - a list of Variables or
Out
instances.
An Out
instance is a structure that lets us attach options to individual output Variable
instances,similarly to how In
lets us attach options to individual input Variable
instances.
Out(variable, borrow=False) returns an Out
instance:
borrow
If
True
, a reference to function’s internal storage is OK. A value returned for this output might be clobbered by running the function again, but the function might be faster.Default:
False
If a single Variable
or Out
instance is given as argument, then the compiled function will return a single value.
If a list of Variable
or Out
instances is given as argument, then the compiled function will return a list of their values.
- >>> import numpy
- >>> from theano.compile.io import Out
- >>> x, y, s = T.matrices('xys')
- >>> # print a list of 2 ndarrays
- >>> fn1 = theano.function([x], [x+x, Out((x+x).T, borrow=True)])
- >>> fn1(numpy.asarray([[1,0],[0,1]]))
- [array([[ 2., 0.],
- [ 0., 2.]]), array([[ 2., 0.],
- [ 0., 2.]])]
- >>> # print a list of 1 ndarray
- >>> fn2 = theano.function([x], [x+x])
- >>> fn2(numpy.asarray([[1,0],[0,1]]))
- [array([[ 2., 0.],
- [ 0., 2.]])]
- >>> # print an ndarray
- >>> fn3 = theano.function([x], outputs=x+x)
- >>> fn3(numpy.asarray([[1,0],[0,1]]))
- array([[ 2., 0.],
- [ 0., 2.]])