|
5 | 5 |
|
6 | 6 | 动静转换(@to_static)通过解析 Python 代码(抽象语法树,下简称:AST) 实现一行代码即可将动态图转为静态图的功能,只需在待转化的函数前添加一个装饰器 ``@paddle.jit.to_static`` 。
|
7 | 7 |
|
8 |
| -如下是使用 @to_static 进行动静转换的两种方式: |
| 8 | +使用 @to_static 即支持 **可训练可部署** ,也支持**只部署**(详见[模型导出](#2)) ,常见使用方式如下: |
9 | 9 |
|
10 | 10 | - 方式一:使用 @to_static 装饰器装饰 ``SimpleNet`` (继承了 ``nn.Layer``) 的 ``forward`` 函数:
|
11 | 11 |
|
|
28 | 28 | net.eval()
|
29 | 29 | x = paddle.rand([2, 10])
|
30 | 30 | y = paddle.rand([2, 3])
|
31 |
| - out = net(x, y) |
32 |
| - paddle.jit.save(net, './net') |
| 31 | + out = net(x, y) # 动转静训练 |
| 32 | + paddle.jit.save(net, './net') # 导出预测模型 |
33 | 33 | ```
|
34 | 34 |
|
35 | 35 | - 方式二:调用 ``paddle.jit.to_static()`` 函数,仅做预测模型导出时推荐此种用法。
|
|
53 | 53 | net = paddle.jit.to_static(net) # 动静转换
|
54 | 54 | x = paddle.rand([2, 10])
|
55 | 55 | y = paddle.rand([2, 3])
|
56 |
| - out = net(x, y) |
57 |
| - paddle.jit.save(net, './net') |
| 56 | + out = net(x, y) # 动转静训练 |
| 57 | + paddle.jit.save(net, './net') # 导出预测模型 |
58 | 58 | ```
|
59 | 59 |
|
60 |
| -方式一和方式二的主要区别是,使用 @to_static 除了支持预测模型导出外,在模型训练时,还会转为静态图子图训练,而方式二仅支持预测模型导出。@to_static 的基本执行流程如下图: |
| 60 | +方式一和方式二的主要区别是,前者直接在 `forward()` 函数定义处装饰,后者显式调用了 `jit.to_static()`方法,默认会对 `net.forward`进行动静转换。 |
| 61 | + |
| 62 | +两种方式均支持动转静训练,如下是@to_static 的基本执行流程: |
61 | 63 |
|
62 | 64 | <img src="https://raw.githubusercontent.com/PaddlePaddle/docs/develop/docs/guides/04_dygraph_to_static/images/to_static_train.png" style="zoom:50%" />
|
63 | 65 |
|
64 | 66 |
|
65 | 67 |
|
66 | 68 | ## 二、动转静模型导出
|
| 69 | +<span id='2'></span> |
67 | 70 |
|
68 | 71 | 动转静模块**是架在动态图与静态图的一个桥梁**,旨在打破动态图模型训练与静态部署的鸿沟,消除部署时对模型代码的依赖,打通与预测端的交互逻辑。下图展示了**动态图模型训练——>动转静模型导出——>静态预测部署**的流程。
|
69 | 72 |
|
@@ -350,22 +353,6 @@ paddle.save(layer_state_dict, "net.pdiparams") # 导出模型
|
350 | 353 |
|
351 | 354 | 上图展示了动态图下**模型训练——>参数导出——>预测部署**的流程。如图中所示,动态图预测部署时,除了已经序列化的参数文件,还须提供**最初的模型组网代码**。
|
352 | 355 |
|
353 |
| -在动态图下,模型代码是 **逐行被解释执行** 的。如: |
354 |
| - |
355 |
| -```python |
356 |
| -import paddle |
357 |
| - |
358 |
| -zeros = paddle.zeros(shape=[1,2], dtype='float32') |
359 |
| -print(zeros) |
360 |
| - |
361 |
| -#Tensor(shape=[1, 2], dtype=float32, place=CPUPlace, stop_gradient=True, |
362 |
| -# [[0., 0.]]) |
363 |
| -``` |
364 |
| - |
365 |
| - |
366 |
| -**从框架层面上,上述的调用链是:** |
367 |
| - |
368 |
| -> 前端 zeros 接口 → core.ops.fill_constant (Pybind11) → 后端 Kernel → 前端 Tensor 输出 |
369 | 356 |
|
370 | 357 | 如下是一个简单的 Model 示例:
|
371 | 358 |
|
@@ -430,20 +417,6 @@ paddle.save(main_program.state_dict(), para_path) # 导出为 .pdiparams
|
430 | 417 |
|
431 | 418 | 在静态图编译期,变量 ``Variable`` 只是**一个符号化表示**,并不像动态图 ``Tensor`` 那样持有实际数据。
|
432 | 419 |
|
433 |
| -```python |
434 |
| -import paddle |
435 |
| -# 开启静态图模式 |
436 |
| -paddle.enable_static() |
437 |
| - |
438 |
| -zeros = paddle.zeros(shape=[1,2], dtype='float32') |
439 |
| -print(zeros) |
440 |
| -# var fill_constant_1.tmp_0 : LOD_TENSOR.shape(1, 2).dtype(float32).stop_gradient(True) |
441 |
| -``` |
442 |
| - |
443 |
| -**从框架层面上,静态图的调用链:** |
444 |
| - |
445 |
| -> layer 组网(前端) → InferShape 检查(编译期) → Executor(执行期) → 逐个执行 OP |
446 |
| -
|
447 | 420 |
|
448 | 421 | 如下是 ``SimpleNet`` 的静态图模式下的组网代码:
|
449 | 422 |
|
|
0 commit comments