Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update doc for AD #4928

Merged
merged 7 commits into from
Jun 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 74 additions & 10 deletions docs/api/paddle/incubate/autograd/Overview_cn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ paddle.incubate.autograd 目录下包含飞桨框架提供的自动微分相关
在高阶微分计算中,随着阶数的升高,输出数量会越来越多,前向微分重要性也会越来越高。
为了更好地支持这些应用场景,需要深度学习框架具备高阶自动微分的能力,且支持前向和反向两种微分模式。


在框架中增加如下功能:

- 设计一套自动微分基础算子
Expand All @@ -66,7 +65,6 @@ paddle.incubate.autograd 目录下包含飞桨框架提供的自动微分相关
自动微分基础算子设计:
自动微分基础算子和原生算子基于同样的数据结构,但是与原生算子体系中的算子不同,这些自动微分基础算子不包含 kernel 实现,只用做表达语义,用于和原生算子体系之间转化规则和自动微分规则的定义,不能直接执行。


原生算子体系和自动微分基础算子体系之间的转化:
一方面,原生算子体系中的算子语义往往比较复杂,需要拆分为多个自动微分基础算子的组合。
另一方面,自动微分基础算子由于没有kernel实现,不能直接执行,在进行完自动微分变换之后,需要转化为同语义的原生算子才可以执行。
Expand All @@ -79,12 +77,76 @@ linearize 和 transpose 程序变换的想法来自 `JAX <https://github.com/goo
规则变化具备可组合性,例如在使用 linearize 和 transpose 完成一阶反向自动微分变换之后,可以在生成的计算图上再次使用 linearize 和 transpose 规则得到二阶反向微分计算图,从而实现高阶自动微分功能。



接口设计与使用案例
==========================
当前阶段优先在静态图中支持了基于自动微分基础算子的自动微分机制,通过全局切换接口 ``enable_prim`` 和 ``disable_prim`` 可以在这套自动微分机制和原始的自动微分机制之间进行切换。

接口层面,基于 orig2prim,linearize 和 transpose 三种变换改写了 ``paddle.static.gradients`` 接口和优化器中的 ``minimize`` 接口,并且对外提供 ``prim2orig`` 接口, 只需要做很少的改动就可以使用新自动微分机制完成自动微分功能。
接口层面,基于 orig2prim,linearize 和 transpose 三种变换改写了 ``paddle.static.gradients`` 接口和优化器中的 ``minimize`` 接口,并且对外提供 ``prim2orig`` 接口, 只需要做很少的改动就可以使用新自动微分机制完成高阶微分的计算。

下边是一个使用示例:

1、首先通过 ``enable_static`` 和 ``enable_prim`` 切换到静态图模式和新自动微分机制。

.. code-block:: python

import numpy as np
import paddle
from paddle.incubate.autograd import enable_prim, prim_enabled, prim2orig

paddle.enable_static()
enable_prim()

2、生成输入数据,配置执行器.

.. code-block:: python

x = np.random.rand(2, 20)

# Set place and excutor
place = paddle.CPUPlace()
if paddle.device.is_compiled_with_cuda():
place = paddle.CUDAPlace(0)
exe = paddle.static.Executor(place)

3、完成 ``program`` 搭建,其中两次调用 ``paddle.static.gradients`` 完成二阶微分运算,调用优化器中的 ``minimize`` 接口完成三阶微分运算,最后调用 ``prim2orig`` 接口将 ``program`` 中的自动微分基础算子转化为等价功能的原生算子。

.. code-block:: python

# Build program
main = paddle.static.Program()
startup = paddle.static.Program()
with paddle.static.program_guard(main, startup):
# Set input and parameter
input_x = paddle.static.data('x', [2, 20], dtype='float64')
input_x.stop_gradient = False
params_w = paddle.static.create_parameter(
shape=[20, 2], dtype='float64', is_bias=False)
params_bias = paddle.static.create_parameter(
shape=[2], dtype='float64', is_bias=True)

# Build network
y = paddle.tanh(paddle.matmul(input_x, params_w) + params_bias)
dy_dx, = paddle.static.gradients([y], [input_x])
d2y_dx2, = paddle.static.gradients([dy_dx], [input_x])
loss = paddle.norm(d2y_dx2, p=2)
opt = paddle.optimizer.Adam(0.01)
_, p_g = opt.minimize(loss)

# Do prim2orig transform.
if prim_enabled():
prim2orig()

4、使用执行器执行 ``program`` 。

.. code-block:: python

# Run program
exe.run(startup)
p_g = exe.run(main,
feed={'x': x},
fetch_list=p_g)

完整的示例代码如下:

.. code-block:: python

Expand Down Expand Up @@ -118,19 +180,21 @@ linearize 和 transpose 程序变换的想法来自 `JAX <https://github.com/goo
# Build network
y = paddle.tanh(paddle.matmul(input_x, params_w) + params_bias)
dy_dx, = paddle.static.gradients([y], [input_x])
loss = paddle.norm(dy_dx, p=2)
d2y_dx2, = paddle.static.gradients([dy_dx], [input_x])
loss = paddle.norm(d2y_dx2, p=2)
opt = paddle.optimizer.Adam(0.01)
_, grads = opt.minimize(loss)
_, p_g = opt.minimize(loss)

# Do prim2orig transform.
if prim_enabled():
prim2orig(main.block(0))
prim2orig()

# Run program
exe.run(startup)
grads = exe.run(main,
feed={'x': x},
fetch_list=grads)
p_g = exe.run(main,
feed={'x': x},
fetch_list=p_g)


演进计划
==========================
Expand Down
3 changes: 2 additions & 1 deletion docs/api/paddle/incubate/autograd/prim2orig_cn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ prim2orig

.. note::
只支持在静态图模式下使用。
参数block必须是None或者是主program的当前block。

对目标程序块中的所有算子进行处理:如果算子是自动微分基础算子,则把该算子替换为一个或者一系列具备等价功能的原生算子,以支持后续执行。


参数
::::::::::::

- **block** (paddle.static.Variable|None可选) - 要进行算子替换处理的目标程序块。默认值是 ``None``,这时候替换处理发生在主程序的当前程序块上。
- **block** (paddle.static.Block|None, 可选) - 要进行算子替换处理的目标程序块。默认值是 ``None`` ,这时候替换处理发生在主程序的当前程序块上。

返回
::::::::::::
Expand Down
8 changes: 6 additions & 2 deletions docs/guides/advanced/autograd_cn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,12 @@ PaddlePaddle的神经网络核心是自动微分,本篇文章主要为你介
.. image:: images/autograd_image_4-4.png


五、基于自动微分基础算子的新自动微分机制
------------------------
在科学计算领域的深度学习任务中,由于引入偏微分方程组,往往需要使用到高阶导数。一些其他复杂的深度学习任务中,有时也会使用到高阶导数。为了更好地支持这些应用场景,飞桨在静态图模式下实现了一套基于自动微分基础算子的新自动微分机制,目前已经支持全联接网络模型,详细介绍可以参考 :ref:`paddle.incubate.autograd <cn_overview_paddle_incubate_autograd>` 。


、总结
、总结
------------------------

本文章主要介绍了如何使用飞桨的自动微分,以及飞桨的自动微分机制。
本文章主要介绍了如何使用飞桨的自动微分,以及飞桨的自动微分机制。