Note
*TODO* Freshen up this old documentation
io - defines pytensor.function [TODO]#
Inputs#
The inputs argument to pytensor.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 pytensor.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 value before running the function, not computed from its owner.name: Any type. (Ifautoname_input==True, defaults tovariable.name). Ifnameis a valid Python identifier, this input can be set bykwarg, and its value can be accessed byself.<name>. The default value isNone.value:Container. The initial value for thisinput. If update is
None, this input acts just like an argument with a default value in Python. If update is notNone, changes to this value will “stick around”, whether due to an update or a user’s explicit action.
update: Variable instance. This expression Variable will replacevalueafter each function call. The default value isNone, indicating that no update is to be done.mutable: Bool (requires value). IfTrue, permit the compiled function to modify the Python object being used as the default value. The default value isFalse.strict: Bool (default:False).Truemeans that the value you pass for this input must have exactly the right type. Otherwise, it may be cast automatically to the proper type.autoname: Bool. If set toTrue, ifnameisNoneand the Variable has a name, it will be taken as the input’s name. If autoname is set toFalse, the name is the exact value passed as the name parameter (possiblyNone).implicit: Bool orNone(default:None)True: This input is implicit in the sense that the user is not allowed to provide a value for it. Requiresvalueto be set.False: The user can provide a value for this input. Be careful whenvalueis a container, because providing an input value will overwrite the content of this container.None: Automatically choose betweenTrueorFalsedepending on the situation. It will be set toFalsein all cases except ifvalueis a container (so that there is less risk of accidentally overwriting its content without being aware of it).
Update#
We can define an update to modify the value of a shared variable after each function call.
>>> import pytensor.tensor as pt
>>> from pytensor import function, shared
>>> s = shared(0.0, name='s')
>>> x = pt.scalar('x')
>>> inc = function([x], s, updates={s: s + x})
Each call to inc returns the current value of s and then updates it:
>>> inc(5) # returns 0, then s becomes 0 + 5
array(0.0)
>>> inc(3) # returns 5, then s becomes 5 + 3
array(5.0)
>>> s.get_value()
array(8.0)
Input Argument Restrictions#
The following restrictions apply to the inputs to pytensor.function:
Every input list element must be a valid
Ininstance, or must be upgradable to a validIninstance. See the shortcut rules below.The same restrictions apply as in Python function definitions: default arguments and keyword arguments must come at the end of the list. Un-named mandatory arguments must come at the beginning of the list.
Names have to be unique within an input list. If multiple inputs have the same name, then the function will raise an exception. [*Which exception?]
Two
Ininstances may not name the same Variable. I.e. you cannot give the same parameter multiple times.
If no name is specified explicitly for an In instance, then its name
will be taken from the Variable’s name. Note that this feature can cause
harmless-looking input lists to not satisfy the two conditions above.
In such cases, Inputs should be named explicitly to avoid problems
such as duplicate names, and named arguments preceding unnamed ones.
This automatic naming feature can be disabled by instantiating an In
instance explicitly with the autoname flag set to False.
Input Shortcuts#
Every element of the inputs list will be upgraded to an In instance if necessary.
a Variable instance
rwill be upgraded likeIn(r)
Outputs#
The outputs argument to function can be one of
None, ora Variable or
Outinstance, ora list of Variables or
Outinstances.
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:
borrowIf
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 pytensor.compile.io import Out
>>> x, y, s = pt.matrices('xys')
>>> # print a list of 2 ndarrays
>>> fn1 = pytensor.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 = pytensor.function([x], [x+x])
>>> fn2(numpy.asarray([[1,0],[0,1]]))
[array([[ 2., 0.],
[ 0., 2.]])]
>>> # print an ndarray
>>> fn3 = pytensor.function([x], outputs=x+x)
>>> fn3(numpy.asarray([[1,0],[0,1]]))
array([[ 2., 0.],
[ 0., 2.]])