@@ -35,86 +35,6 @@ net = paddle.jit.to_static(net) # 动静转换
3535<img src =" https://raw.githubusercontent.com/PaddlePaddle/docs/develop/docs/guides/04_dygraph_to_static/images/to_static_train.png " style =" zoom :50% " />
3636
3737
38- ### 1.1 动态图 layer 生成 Program
39-
40- 上述样例中的 `` forward `` 函数包含两行组网代码: `` Linear `` 和 `` add `` 操作。以 `` Linear `` 为例,在 Paddle 的框架底层,每个 Paddle 的组网 API 的实现包括两个分支:
41-
42- ``` python
43-
44- class Linear (... ):
45- def __init__ (self , ...):
46- # ...(略)
47-
48- def forward (self , input ):
49-
50- if in_dygraph_mode(): # 动态图分支
51- core.ops.matmul(input , self .weight, pre_bias, ... )
52- return out
53- else : # 静态图分支
54- self ._helper.append_op(type = " matmul" , inputs = inputs, ... ) # <----- 生成一个 Op
55- if self .bias is not None :
56- self ._helper.append_op(type = ' elementwise_add' , ... ) # <----- 生成一个 Op
57-
58- return out
59- ```
60-
61- 动态图 `` layer `` 生成 `` Program `` ,其实是开启 `` paddle.enable_static() `` 时,在静态图下逐行执行用户定义的组网代码,依次添加(对应 `` append_op `` 接口) 到默认的主 Program(即 `` main_program `` ) 中。
62-
63- ### 1.2 动态图 Tensor 转为静态图 Variable
64-
65- 上面提到,所有的组网代码都会在静态图模式下执行,以生成完整的 `` Program `` 。** 但静态图 `` append_op `` 有一个前置条件必须满足:**
66-
67- > ** 前置条件** :append_op() 时,所有的 inputs,outputs 必须都是静态图的 Variable 类型,不能是动态图的 Tensor 类型。
68-
69-
70- ** 原因** :静态图下,操作的都是** 描述类单元** :计算相关的 `` OpDesc `` ,数据相关的 `` VarDesc `` 。可以分别简单地理解为 `` Program `` 中的 `` Op `` 和 `` Variable `` 。
71-
72- 因此,在动转静时,我们在需要在** 某个统一的入口处** ,将动态图 `` Layers `` 中 `` Tensor `` 类型(包含具体数据)的 `` Weight `` 、`` Bias `` 等变量转换为** 同名的静态图 `` Variable `` ** 。
73-
74- + ParamBase &rarr ; Parameters
75- + VarBase &rarr ; Variable
76-
77- 技术实现上,我们选取了框架层面两个地方作为类型** 转换的入口** :
78-
79- + `` Paddle.nn.Layer `` 基类的 `` __call__ `` 函数
80- ``` python
81- def __call__ (self , * inputs , ** kwargs ):
82- # param_guard 会对将 Tensor 类型的 Param 和 buffer 转为静态图 Variable
83- with param_guard(self ._parameters), param_guard(self ._buffers):
84- # ... forward_pre_hook 逻辑
85-
86- outputs = self .forward(* inputs, ** kwargs) # 此处为forward函数
87-
88- # ... forward_post_hook 逻辑
89-
90- return outpus
91- ```
92-
93- + `` Block.append_op`` 函数中,生成 `` Op`` 之前
94- ```python
95- def append_op (self , * args , ** kwargs ):
96- if in_dygraph_mode():
97- # ... (动态图分支)
98- else :
99- inputs= kwargs.get(" inputs" , None )
100- outputs= kwargs.get(" outputs" , None )
101- # param_guard 会确保将 Tensor 类型的 inputs 和 outputs 转为静态图 Variable
102- with param_guard(inputs), param_guard(outputs):
103- op = Operator(
104- block = self ,
105- desc = op_desc,
106- type = kwargs.get(" type" , None ),
107- inputs = inputs,
108- outputs = outputs,
109- attrs = kwargs.get(" attrs" , None ))
110- ```
111-
112-
113- 以上,是动态图转为静态图的两个核心逻辑,总结如下:
114-
115- + 动态图 `` layer`` 调用在动转静时会走底层 `` append_op`` 的分支,以生成 `` Program``
116- + 动态图 `` Tensor`` 转为静态图 `` Variable`` ,并确保编译期的 `` InferShape`` 正确执行
117-
11838
11939## 二、 输入层 InputSpec
12040
@@ -419,6 +339,89 @@ def depend_tensor_while(x):
419339
420340## 五、 Parameters 与 Buffers
421341
342+ ### 1.1 动态图 layer 生成 Program
343+
344+ 文档开始的样例中 `` forward `` 函数包含两行组网代码: `` Linear `` 和 `` add `` 操作。以 `` Linear `` 为例,在 Paddle 的框架底层,每个 Paddle 的组网 API 的实现包括两个分支:
345+
346+ ``` python
347+
348+ class Linear (... ):
349+ def __init__ (self , ...):
350+ # ...(略)
351+
352+ def forward (self , input ):
353+
354+ if in_dygraph_mode(): # 动态图分支
355+ core.ops.matmul(input , self .weight, pre_bias, ... )
356+ return out
357+ else : # 静态图分支
358+ self ._helper.append_op(type = " matmul" , inputs = inputs, ... ) # <----- 生成一个 Op
359+ if self .bias is not None :
360+ self ._helper.append_op(type = ' elementwise_add' , ... ) # <----- 生成一个 Op
361+
362+ return out
363+ ```
364+
365+ 动态图 `` layer `` 生成 `` Program `` ,其实是开启 `` paddle.enable_static() `` 时,在静态图下逐行执行用户定义的组网代码,依次添加(对应 `` append_op `` 接口) 到默认的主 Program(即 `` main_program `` ) 中。
366+
367+ ### 1.2 动态图 Tensor 转为静态图 Variable
368+
369+ 上面提到,所有的组网代码都会在静态图模式下执行,以生成完整的 `` Program `` 。** 但静态图 `` append_op `` 有一个前置条件必须满足:**
370+
371+ > ** 前置条件** :append_op() 时,所有的 inputs,outputs 必须都是静态图的 Variable 类型,不能是动态图的 Tensor 类型。
372+
373+
374+ ** 原因** :静态图下,操作的都是** 描述类单元** :计算相关的 `` OpDesc `` ,数据相关的 `` VarDesc `` 。可以分别简单地理解为 `` Program `` 中的 `` Op `` 和 `` Variable `` 。
375+
376+ 因此,在动转静时,我们在需要在** 某个统一的入口处** ,将动态图 `` Layers `` 中 `` Tensor `` 类型(包含具体数据)的 `` Weight `` 、`` Bias `` 等变量转换为** 同名的静态图 `` Variable `` ** 。
377+
378+ + ParamBase &rarr ; Parameters
379+ + VarBase &rarr ; Variable
380+
381+ 技术实现上,我们选取了框架层面两个地方作为类型** 转换的入口** :
382+
383+ + `` Paddle.nn.Layer `` 基类的 `` __call__ `` 函数
384+ ``` python
385+ def __call__ (self , * inputs , ** kwargs ):
386+ # param_guard 会对将 Tensor 类型的 Param 和 buffer 转为静态图 Variable
387+ with param_guard(self ._parameters), param_guard(self ._buffers):
388+ # ... forward_pre_hook 逻辑
389+
390+ outputs = self .forward(* inputs, ** kwargs) # 此处为forward函数
391+
392+ # ... forward_post_hook 逻辑
393+
394+ return outpus
395+ ```
396+
397+ + `` Block.append_op`` 函数中,生成 `` Op`` 之前
398+ ```python
399+ def append_op (self , * args , ** kwargs ):
400+ if in_dygraph_mode():
401+ # ... (动态图分支)
402+ else :
403+ inputs= kwargs.get(" inputs" , None )
404+ outputs= kwargs.get(" outputs" , None )
405+ # param_guard 会确保将 Tensor 类型的 inputs 和 outputs 转为静态图 Variable
406+ with param_guard(inputs), param_guard(outputs):
407+ op = Operator(
408+ block = self ,
409+ desc = op_desc,
410+ type = kwargs.get(" type" , None ),
411+ inputs = inputs,
412+ outputs = outputs,
413+ attrs = kwargs.get(" attrs" , None ))
414+ ```
415+
416+
417+ 以上,是动态图转为静态图的两个核心逻辑,总结如下:
418+
419+ + 动态图 `` layer`` 调用在动转静时会走底层 `` append_op`` 的分支,以生成 `` Program``
420+ + 动态图 `` Tensor`` 转为静态图 `` Variable`` ,并确保编译期的 `` InferShape`` 正确执行
421+
422+
423+ # ## 1.3 Buffer 变量
424+
422425** 什么是 `` Buffers`` 变量?**
423426
424427+ ** Parameters** :`` persistable`` 为 `` True `` ,且每个 batch 都被 Optimizer 更新的变量
@@ -471,4 +474,3 @@ class SimpleNet(paddle.nn.Layer):
471474总结一下 `` buffers `` 的用法:
472475
473476+ 若某个非 `` Tensor `` 数据需要当做 `` Persistable `` 的变量序列化到磁盘,则最好在 `` __init__ `` 中调用 `` self.XX= paddle.to_tensor(xx) `` 接口转为 `` buffer `` 变量
474-
0 commit comments