Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
150add2c
提交
150add2c
authored
1月 12, 2022
作者:
Brandon T. Willard
提交者:
Brandon T. Willard
1月 13, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update developer documentation on Type to include new partial shape information
上级
e6f9689e
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
79 行增加
和
86 行删除
+79
-86
graphstructures.rst
doc/extending/graphstructures.rst
+33
-30
type.rst
doc/extending/type.rst
+0
-0
shape_info.rst
doc/tutorial/shape_info.rst
+46
-56
没有找到文件。
doc/extending/graphstructures.rst
浏览文件 @
150add2c
...
@@ -203,36 +203,39 @@ structures, code going like ``def f(x): ...`` would produce an :class:`Op` for
...
@@ -203,36 +203,39 @@ structures, code going like ``def f(x): ...`` would produce an :class:`Op` for
:class:`Type`
:class:`Type`
-------------
-------------
A :class:`Type` in Aesara represents a set of constraints on potential
A :class:`Type` in Aesara provides static information (or constraints) about
data objects. These constraints allow Aesara to tailor C code to handle
data objects in a graph. The information provided by :class:`Type`\s allows
them and to statically optimize the computation graph. For instance,
Aesara to perform optimizations and produce more efficient compiled code.
the :ref:`irow <libdoc_tensor_creation>` type in the :mod:`aesara.tensor` package
gives the following constraints on the data the :class:`Variable`\s of type ``irow``
Every symbolic :class:`Variable` in an Aesara graph has an associated
may contain:
:class:`Type` instance, and :class:`Type`\s also serve as a means of
constructing :class:`Variable` instances. In other words, :class:`Type`\s and
#. Must be an instance of :class:`numpy.ndarray`: ``isinstance(x, numpy.ndarray)``
:class:`Variable`\s go hand-in-hand.
#. Must be an array of 32-bit integers: ``str(x.dtype) == 'int32'``
#. Must have a shape of 1xN: ``len(x.shape) == 2 and x.shape[0] == 1``
For example, :ref:`aesara.tensor.irow <libdoc_tensor_creation>` is an instance of a
:class:`Type` and it can be used to construct variables as follows:
Knowing these restrictions, Aesara may generate C code for addition, etc.
that declares the right data types and that contains the right number
>>> from aesara.tensor import irow
of loops over the dimensions.
>>> irow()
<TensorType(int32, (1, None))>
Note that an Aesara :class:`Type` is not equivalent to a Python type or
class. Indeed, in Aesara, :ref:`irow <libdoc_tensor_creation>` and :ref:`dmatrix
As the string print-out shows, `irow` specifies the following information about
<libdoc_tensor_creation>` both use :class:`numpy.ndarray` as the underlying type
the :class:`Variable`\s it constructs:
for doing computations and storing data, yet they are different Aesara
:class:`Type`\s. Indeed, the constraints set by `dmatrix` are:
#. They represent tensors that are backed by :class:`numpy.ndarray`\s.
This comes from the fact that `irow` is an instance of :class:`TensorType`,
#. Must be an instance of :class:`numpy.ndarray`: ``isinstance(x, numpy.ndarray)``
which is the base :class:`Type` for symbolic :class:`numpy.ndarray`\s.
#. Must be an array of 64-bit floating point numbers: ``str(x.dtype) == 'float64'``
#. They represent arrays of 32-bit integers (i.e. from the ``int32``).
#. Must have a shape of ``MxN``, no restriction on ``M`` or ``N``: ``len(x.shape) == 2``
#. They represent arrays with shapes of :math:`1 \times N`, or, in code, ``(1,
None)``, where ``None`` represents any shape value.
These restrictions are different from those of ``irow`` which are listed above.
Note that Aesara :class:`Type`\s are not necessarily equivalent to Python types or
There are cases in which a :class:`Type` can fully correspond to a Python type,
classes. Aesara's :class:`TensorType`'s, like `irow`, use :class:`numpy.ndarray`
such as the `double`\ :class:`Type`, which corresponds to
as the underlying Python type for performing computations and storing data, but
Python's ``float``.
:class:`numpy.ndarray`\s model a much wider class of arrays than most :class:`TensorType`\s.
In other words, Aesara :class:`Type`'s try to be more specific.
For more information see :ref:`aesara_type`.
.. index::
.. index::
single: Variable
single: Variable
...
...
doc/extending/type.rst
浏览文件 @
150add2c
差异被折叠。
点击展开。
doc/tutorial/shape_info.rst
浏览文件 @
150add2c
...
@@ -4,25 +4,21 @@
...
@@ -4,25 +4,21 @@
How Shape Information is Handled by Aesara
How Shape Information is Handled by Aesara
==========================================
==========================================
It is not possible to strictly enforce the shape of an Aesara variable when
Currently, information regarding shape is used in the following ways by Aesara:
building a graph since the particular value provided at run-time for a parameter of a
Aesara function may condition the shape of the Aesara variables in its graph.
Currently, information regarding shape is used in two ways in Aesara:
- To generate faster C code for the 2d convolution on the CPU and the GPU,
when the exact output shape is known in advance.
- To remove computations in the graph when we only want to know the
- To remove computations in the graph when we only want to know the
shape, but not the actual value of a variable. This is done with the
shape, but not the actual value of a variable. This is done with the
`Op.infer_shape` method.
:meth:`Op.infer_shape` method.
- To generate faster compiled code (e.g. for a 2D convolution).
Example:
Example:
>>> import aesara
>>> import aesara
>>> x = aesara.tensor.matrix('x')
>>> x = aesara.tensor.matrix('x')
>>> f = aesara.function([x], (x ** 2).shape)
>>> f = aesara.function([x], (x ** 2).shape)
>>> aesara.
printing.debugprint(f) # doctest: +NORMALIZE_WHITESPACE
>>> aesara.
dprint(f)
MakeVector{dtype='int64'} [id A] '' 2
MakeVector{dtype='int64'} [id A] '' 2
|Shape_i{0} [id B] '' 1
|Shape_i{0} [id B] '' 1
| |x [id C]
| |x [id C]
...
@@ -30,15 +26,46 @@ MakeVector{dtype='int64'} [id A] '' 2
...
@@ -30,15 +26,46 @@ MakeVector{dtype='int64'} [id A] '' 2
|x [id C]
|x [id C]
The output of this compiled function does not contain any multiplication
The output of this compiled function does not contain any multiplication or
or power. Aesara has removed them to compute directly the shape of the
power computations; Aesara has removed them to compute the shape of the output
output.
directly.
Aesara propagates information about shapes within a graph using specialized
:class:`Op`\s and static :class:`Type` information (see :ref:`aesara_type`).
Specifying Exact Shape
======================
Currently, specifying a shape is not as easy and flexible as we wish and we plan some
upgrade. Here is the current state of what can be done:
- You can pass the shape info directly to the ``ConvOp`` created
when calling ``conv2d``. You simply set the parameters ``image_shape``
and ``filter_shape`` inside the call. They must be tuples of 4
elements. For example:
.. code-block:: python
aesara.tensor.nnet.conv2d(..., image_shape=(7, 3, 5, 5), filter_shape=(2, 3, 4, 4))
- You can use the ``SpecifyShape`` op to add shape information anywhere in the
graph. This allows to perform some optimizations. In the following example,
this makes it possible to precompute the Aesara function to a constant.
>>> import aesara
>>> x = aesara.tensor.matrix()
>>> x_specify_shape = aesara.tensor.specify_shape(x, (2, 2))
>>> f = aesara.function([x], (x_specify_shape ** 2).shape)
>>> aesara.printing.debugprint(f) # doctest: +NORMALIZE_WHITESPACE
DeepCopyOp [id A] '' 0
|TensorConstant{(2,) of 2} [id B]
Shape Inference Problem
Problems with Shape inference
=======================
=======================
======
Aesara propagates information about shape in the graph. Sometimes this
Sometimes this can lead to errors. Consider this example:
can lead to errors. Consider this example:
>>> import numpy
>>> import numpy
>>> import aesara
>>> import aesara
...
@@ -75,7 +102,7 @@ Traceback (most recent call last):
...
@@ -75,7 +102,7 @@ Traceback (most recent call last):
ValueError: ...
ValueError: ...
As you can see, when asking only for the shape of some computation (``join`` in the
As you can see, when asking only for the shape of some computation (``join`` in the
example), an inferred shape is computed directly, without executing
example
above
), an inferred shape is computed directly, without executing
the computation itself (there is no ``join`` in the first output or debugprint).
the computation itself (there is no ``join`` in the first output or debugprint).
This makes the computation of the shape faster, but it can also hide errors. In
This makes the computation of the shape faster, but it can also hide errors. In
...
@@ -93,40 +120,3 @@ optimization, using the Aesara flag
...
@@ -93,40 +120,3 @@ optimization, using the Aesara flag
same effect by running in the modes ``FAST_COMPILE`` (it will not apply this
same effect by running in the modes ``FAST_COMPILE`` (it will not apply this
optimization, nor most other optimizations) or ``DebugMode`` (it will test
optimization, nor most other optimizations) or ``DebugMode`` (it will test
before and after all optimizations (much slower)).
before and after all optimizations (much slower)).
Specifying Exact Shape
======================
Currently, specifying a shape is not as easy and flexible as we wish and we plan some
upgrade. Here is the current state of what can be done:
- You can pass the shape info directly to the ``ConvOp`` created
when calling ``conv2d``. You simply set the parameters ``image_shape``
and ``filter_shape`` inside the call. They must be tuples of 4
elements. For example:
.. code-block:: python
aesara.tensor.nnet.conv2d(..., image_shape=(7, 3, 5, 5), filter_shape=(2, 3, 4, 4))
- You can use the ``SpecifyShape`` op to add shape information anywhere in the
graph. This allows to perform some optimizations. In the following example,
this makes it possible to precompute the Aesara function to a constant.
>>> import aesara
>>> x = aesara.tensor.matrix()
>>> x_specify_shape = aesara.tensor.specify_shape(x, (2, 2))
>>> f = aesara.function([x], (x_specify_shape ** 2).shape)
>>> aesara.printing.debugprint(f) # doctest: +NORMALIZE_WHITESPACE
DeepCopyOp [id A] '' 0
|TensorConstant{(2,) of 2} [id B]
Future Plans
============
The parameter "constant shape" will be added to ``aesara.shared()``. This is probably
the most frequent occurrence with ``shared`` variables. It will make the code
simpler and will make it possible to check that the shape does not change when
updating the ``shared`` variable.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论