API Documentation#
This documentation covers PyTensor module-wise. This is suited to finding the Types and Ops that you can use to build and compile expression graphs.
Modules#
compile
– Transforming Expression Graphs to Functionsconfig
– PyTensor Configurationd3viz
– d3viz: Interactive visualization of PyTensor compute graphsgraph
– PyTensor Graph Internalsgradient
– Symbolic Differentiationmisc.pkl_utils
- Tools for serialization.printing
– Graph Printing and Symbolic Print Statementscalar
– Symbolic Scalar Types, Ops [doc TODO]scan
– Looping in PyTensorsparse
– Symbolic Sparse Matricessparse
– Sparse Opsparse.sandbox
– Sparse Op Sandboxtensor
– Tensor operations in PyTensortyped_list
– Typed List
There are also some top-level imports that you might find more convenient:
Graph#
Alias for
pytensor.compile.sharedvalue.shared()
- pytensor.function(...)[source]#
Alias for
pytensor.compile.function.function()
- pytensor.clone_replace(...)[source]#
Clone a graph and replace subgraphs within it.
It returns a copy of the initial subgraph with the corresponding substitutions.
- Parameters:
output – PyTensor expression that represents the computational graph.
replace – Dictionary describing which subgraphs should be replaced by what.
rebuild_kwds – Keywords to
rebuild_collect_shared
.
Alias for
pytensor.graph.basic.clone_replace()
Control flow#
- pytensor.scan(...)[source]#
This function constructs and applies a
Scan
Op
to the provided arguments.- Parameters:
fn –
fn
is a function that describes the operations involved in onestep of
scan
.fn
should construct variables describing the output of one iteration step. It should expect as inputVariable
s representing all the slices of the input sequences and previous values of the outputs, as well as all other arguments given to scan asnon_sequences
. The order in which scan passes these variables tofn
is the following :all time slices of the first sequence
all time slices of the second sequence
…
all time slices of the last sequence
all past slices of the first output
all past slices of the second output
…
all past slices of the last output
- all other arguments (the list given as
non_sequences
to scan
)
- all other arguments (the list given as
The order of the sequences is the same as the one in the list
sequences
given toscan
. The order of the outputs is the same as the order ofoutputs_info
. For any sequence or output the order of the time slices is the same as the one in which they have been given as taps. For example if one writes the following :scan( fn, sequences=[ dict(input=Sequence1, taps=[-3, 2, -1]), Sequence2, dict(input=Sequence3, taps=3), ], outputs_info=[ dict(initial=Output1, taps=[-3, -5]), dict(initial=Output2, taps=None), Output3, ], non_sequences=[Argument1, Argument2], )
fn
should expect the following arguments in this given order:sequence1[t-3]
sequence1[t+2]
sequence1[t-1]
sequence2[t]
sequence3[t+3]
output1[t-3]
output1[t-5]
output3[t-1]
argument1
argument2
The list of
non_sequences
can also contain shared variables used in the function, thoughscan
is able to figure those out on its own so they can be skipped. For the clarity of the code we recommend though to provide them toscan
. To some extendscan
can also figure out othernon sequences
(not shared) even if not passed toscan
(but used byfn
). A simple example of this would be :import pytensor.tensor as pt W = pt.matrix() W_2 = W**2
- def f(x):
return pt.dot(x, W_2)
The function
fn
is expected to return two things. One is a list of outputs ordered in the same order asoutputs_info
, with the difference that there should be only one output variable per output initial state (even if no tap value is used). Secondlyfn
should return an update dictionary (that tells how to update any shared variable after each iteration step). The dictionary can optionally be given as a list of tuples. There is no constraint on the order of these two list,fn
can return either(outputs_list, update_dictionary)
or(update_dictionary, outputs_list)
or just one of the two (in case the other is empty).To use
scan
as awhile
loop, the user needs to change the functionfn
such that also a stopping condition is returned. To do so, one needs to wrap the condition in anuntil
class. The condition should be returned as a third element, for example:... return [y1_t, y2_t], {x: x + 1}, until(x < 50)
Note that a number of steps–considered in here as the maximum number of steps–is still required even though a condition is passed. It is used to allocate memory if needed.
- sequences
sequences
is the list ofVariable
s ordict
s describing the sequencesscan
has to iterate over. If a sequence is given as wrapped in adict
, then a set of optional information can be provided about the sequence. Thedict
should have the following keys:input
(mandatory) –Variable
representing the sequence.taps
– Temporal taps of the sequence required byfn
. They are provided as a list of integers, where a valuek
impiles that at iteration stept
scan will pass tofn
the slicet+k
. Default value is[0]
All
Variable
s in the listsequences
are automatically wrapped into adict
wheretaps
is set to[0]
- outputs_info
outputs_info
is the list ofVariable
s ordict
s describing the initial state of the outputs computed recurrently. When the initial states are given asdict
s, optional information can be provided about the output corresponding to those initial states. Thedict
should have the following keys:initial
– AVariable
that represents the initial state of a given output. In case the output is not computed recursively (e.g. amap
-like function) and does not require an initial state, this field can be skipped. Given that only the previous time step of the output is used byfn
, the initial state should have the same shape as the output and should not involve a downcast of the data type of the output. If multiple time taps are used, the initial state should have one extra dimension that covers all the possible taps. For example if we use-5
,-2
and-1
as past taps, at step0
,fn
will require (by an abuse of notation)output[-5]
,output[-2]
andoutput[-1]
. This will be given by the initial state, which in this case should have the shape(5,) + output.shape
. If thisVariable
containing the initial state is calledinit_y
theninit_y[0]
corresponds tooutput[-5]
.init_y[1]
corresponds tooutput[-4]
,init_y[2]
corresponds tooutput[-3]
,init_y[3]
corresponds tooutput[-2]
,init_y[4]
corresponds tooutput[-1]
. While this order might seem strange, it comes natural from splitting an array at a given point. assume that we have a arrayx
, and we choosek
to be time step0
. Then our initial state would bex[:k]
, while the output will bex[k:]
. Looking at this split, elements inx[:k]
are ordered exactly like those ininit_y
.taps
– Temporal taps of the output that will be passed tofn
. They are provided as a list of negative integers, where a valuek
implies that at iteration stept
scan will pass tofn
the slicet+k
.
scan
will follow this logic if partial information is given:If an output is not wrapped in a
dict
,scan
will wrap it in one assuming that you use only the last step of the output (i.e. it makes your tap value list equal to[-1]
).If you wrap an output in a
dict
and you do not provide any taps but you provide an initial state it will assume that you are using only a tap value of-1
.If you wrap an output in a
dict
but you do not provide any initial state, it assumes that you are not using any form of taps.If you provide a
None
instead of aVariable
or a emptydict
scan
assumes that you will not use any taps for this output (like for example in case of amap
)
If
outputs_info
is an emptylist
orNone
,scan
assumes that no tap is used for any of the outputs. If information is provided just for a subset of the outputs, an exception is raised, because there is no convention on how scan should map the provided information to the outputs offn
.- non_sequences
non_sequences
is the list of arguments that are passed tofn
at each steps. One can choose to exclude variables used infn
from this list, as long as they are part of the computational graph, although–for clarity–this is not encouraged.- n_steps
n_steps
is the number of steps to iterate given as anint
or a scalarVariable
. If any of the input sequences do not have enough elements,scan
will raise an error. If the value is0
, the outputs will have0
rows. Ifn_steps
is not provided,scan
will figure out the amount of steps it should run given its input sequences.n_steps < 0
is not supported anymore.- truncate_gradient
truncate_gradient
is the number of steps to use in truncated back-propagation through time (BPTT). If you compute gradients through aScan
Op
, they are computed using BPTT. By providing a different value then-1
, you choose to use truncated BPTT instead of classical BPTT, where you go for onlytruncate_gradient
number of steps back in time.- go_backwards
go_backwards
is a flag indicating ifscan
should go backwards through the sequences. If you think of each sequence as indexed by time, making this flagTrue
would mean thatscan
goes back in time, namely that for any sequence it starts from the end and goes towards0
.- name
When profiling
scan
, it is helpful to provide a name for any instance ofscan
. For example, the profiler will produce an overall profile of your code as well as profiles for the computation of one step of each instance ofScan
. Thename
of the instance appears in those profiles and can greatly help to disambiguate information.- mode
The mode used to compile the inner-graph. If you prefer the computations of one step of
scan
to be done differently then the entire function, you can use this parameter to describe how the computations in this loop are done (seepytensor.function
for details about possible values and their meaning).- profile
If
True
or a non-empty string, a profile object will be created and attached to the inner graph ofScan
. Whenprofile
isTrue
, the profiler results will use the name of theScan
instance, otherwise it will use the passed string. The profiler only collects and prints information when running the inner graph with theCVM
Linker
.- allow_gc
Set the value of
allow_gc
for the internal graph of theScan
. If set toNone
, this will use the value ofpytensor.config.scan__allow_gc
.The full
Scan
behavior related to allocation is determined by this value and the flagpytensor.config.allow_gc
. If the flagallow_gc
isTrue
(default) and thisallow_gc
isFalse
(default), then we letScan
allocate all intermediate memory on the first iteration, and they are not garbage collected after that first iteration; this is determined byallow_gc
. This can speed up allocation of the subsequent iterations. All those temporary allocations are freed at the end of all iterations; this is what the flagpytensor.config.allow_gc
means.- strict
If
True
, all the shared variables used infn
must be provided as a part ofnon_sequences
orsequences
.- return_list
If
True
, will always return alist
, even if there is only one output.
- Returns:
tuple
of the form(outputs, updates)
.outputs
is either aVariable
or alist
ofVariable
s representing the outputs in the same order as inoutputs_info
.updates
is a subclass ofdict
specifying the update rules for all shared variables used inScan
. Thisdict
should be passed topytensor.function
when you compile your function.- Return type:
tuple
Alias for
pytensor.scan.basic.scan()
Convert to Variable#
- pytensor.as_symbolic(...)[source]#
Convert
x
into an equivalent PyTensorVariable
.- Parameters:
x – The object to be converted into a
Variable
type. Anumpy.ndarray
argument will not be copied, but a list of numbers will be copied to make annumpy.ndarray
.name – If a new
Variable
instance is created, it will be named with this string.kwargs – Options passed to the appropriate sub-dispatch functions. For example,
ndim
anddtype
can be passed whenx
is annumpy.ndarray
orNumber
type.
- Raises:
TypeError – If
x
cannot be converted to aVariable
.
Debug#
- pytensor.dprint(...)[source]#
Print a graph as text.
Each line printed represents a
Variable
in a graph. The indentation of lines corresponds to its depth in the symbolic graph. The first part of the text identifies whether it is an input or the output of someApply
node. The second part of the text is an identifier of theVariable
.If a
Variable
is encountered multiple times in the depth-first search, it is only printed recursively the first time. Later, just theVariable
identifier is printed.If an
Apply
node has multiple outputs, then a.N
suffix will be appended to theApply
node’s identifier, indicating to which output a line corresponds.- Parameters:
graph_like – The object(s) to be printed.
depth – Print graph to this depth (
-1
for unlimited).print_type – If
True
, print theType
s of eachVariable
in the graph.file – When
file
extendsTextIO
, print to it; whenfile
is equal to"str"
, return a string; whenfile
isNone
, print tosys.stdout
.id_type –
- Determines the type of identifier used for
Variable
s: "id"
: print the python id value,"int"
: print integer character,"CHAR"
: print capital character,"auto"
: print theVariable.auto_name
values,""
: don’t print an identifier.
- Determines the type of identifier used for
stop_on_name – When
True
, if a node in the graph has a name, we don’t print anything below it.done – A
dict
where we store the ids of printed nodes. Useful to have multiple call todebugprint
share the same ids.print_storage – If
True
, this will print the storage map for PyTensor functions. When combined withallow_gc=False
, after the execution of an PyTensor function, the output will show the intermediate results.used_ids – A map between nodes and their printed ids.
print_op_info – Print extra information provided by the relevant
Op
s. For example, print the tap information forScan
inputs and outputs.print_destroy_map – Whether to print the
destroy_map
s of printed objectsprint_view_map – Whether to print the
view_map
s of printed objectsprint_fgraph_inputs – Print the inputs of
FunctionGraph
s.
- Return type:
A string representing the printed graph, if
file
is a string, elsefile
.
Alias for
pytensor.printing.debugprint()