未验证 提交 4f6c833d 编写于 作者: C Chen Weihang 提交者: GitHub

Add new paddle.save/load cn doc (#2669)

* add paddle new save load doc

* move static save apis & polish multiple details

* add api mapping

* move apis place

* fix example code error

* polish model save load guide

* polish example code

* fix details example error

* polish guide doc

* change title format

* remove history reason

* remove other history reason

* add enable_static for old save/load

* add enable_static for old api
上级 c60f0390
......@@ -60,7 +60,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
......
......@@ -60,7 +60,7 @@ Load model and run it in static graph mode:
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance:
......
......@@ -7,8 +7,8 @@ save
.. py:function:: paddle.fluid.save(program, model_path)
:api_attr: 声明式编程模式(静态图)
:alias_main: paddle.save
:alias: paddle.save,paddle.tensor.save,paddle.tensor.io.save
:alias_main: paddle.static.save
:alias: paddle.static.save
:old_api: paddle.fluid.save
......
......@@ -6,8 +6,8 @@ load
.. py:function:: paddle.fluid.io.load(program, model_path, executor=None, var_list=None)
:api_attr: 声明式编程模式(静态图)
:alias_main: paddle.load
:alias: paddle.load,paddle.tensor.load,paddle.tensor.io.load
:alias_main: paddle.static.load
:alias: paddle.static.load
:old_api: paddle.fluid.io.load
......
......@@ -551,7 +551,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0])
# 声明式编程中需要使用执行器执行之前已经定义好的网络
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
# 声明式编程中需要调用执行器的run方法执行计算过程
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
```
......
......@@ -8,7 +8,7 @@ paddle.nn.functional.common.alpha_dropout paddle.nn.functional.alpha_dropout
paddle.nn.functional.activation.log_sigmoid paddle.nn.functional.log_sigmoid
paddle.fluid.executor.Executor paddle.static.Executor
paddle.nn.functional.pooling.avg_pool2d paddle.nn.functional.avg_pool2d
paddle.fluid.dygraph.checkpoint.load_dygraph paddle.load,paddle.framework.load
paddle.framework.io.load paddle.load,paddle.framework.load
paddle.fluid.dygraph.container.Sequential paddle.nn.Sequential
paddle.fluid.dygraph.BilinearTensorProduct paddle.nn.BilinearTensorProduct,paddle.nn.layer.BilinearTensorProduct,paddle.nn.layer.common.BilinearTensorProduct
paddle.fluid.layers.box_coder paddle.nn.functional.box_coder,paddle.nn.functional.vision.box_coder
......@@ -251,7 +251,7 @@ paddle.nn.functional.activation.prelu paddle.nn.functional.prelu
paddle.tensor.linalg.matmul paddle.matmul,paddle.tensor.matmul
paddle.fluid.layers.generate_proposals paddle.nn.functional.generate_proposals,paddle.nn.functional.vision.generate_proposals
paddle.nn.layer.loss.SmoothL1Loss paddle.nn.SmoothL1Loss,paddle.nn.layer.SmoothL1Loss
paddle.fluid.dygraph.checkpoint.save_dygraph paddle.save,paddle.framework.save
paddle.framework.io.save paddle.save,paddle.framework.save
paddle.fluid.core paddle.framework.core
paddle.nn.functional.vision.grid_sample paddle.nn.functional.grid_sample
paddle.tensor.random.rand paddle.rand,paddle.tensor.rand
......@@ -282,7 +282,7 @@ paddle.framework.get_default_dtype paddle.get_default_dtype
paddle.fluid.layers.atan paddle.atan,paddle.tensor.atan,paddle.tensor.math.atan
paddle.fluid.layers.pad2d paddle.nn.functional.pad2d,paddle.nn.functional.common.pad2d
paddle.nn.layer.pooling.MaxPool3d paddle.nn.MaxPool3d,paddle.nn.layer.MaxPool3d
paddle.fluid.io.load paddle.static.load,paddle.tensor.load,paddle.tensor.io.load
paddle.fluid.io.load paddle.static.load
paddle.fluid.dygraph.learning_rate_scheduler.ExponentialDecay paddle.ExponentialDecay,paddle.framework.ExponentialDecay
paddle.fluid.layers.conv3d paddle.static.nn.conv3d
paddle.nn.layer.activation.Softmax paddle.nn.Softmax
......@@ -447,7 +447,7 @@ paddle.tensor.stat.numel paddle.numel,paddle.tensor.numel
paddle.nn.functional.activation.relu6 paddle.nn.functional.relu6
paddle.tensor.math.cumsum paddle.cumsum,paddle.tensor.cumsum
paddle.fluid.layers.resize_trilinear paddle.nn.functional.resize_trilinear,paddle.nn.functional.vision.resize_trilinear
paddle.fluid.save paddle.static.save,paddle.tensor.save,paddle.tensor.io.save
paddle.fluid.io.save paddle.static.save
paddle.fluid.layers.scale paddle.scale,paddle.tensor.scale,paddle.tensor.math.scale
paddle.fluid.framework.default_startup_program paddle.static.default_startup_program
paddle.fluid.layers.noam_decay paddle.nn.functional.noam_decay,paddle.nn.functional.learning_rate.noam_decay
......
......@@ -4,17 +4,17 @@ load
----
.. py:function:: paddle.load(model_path, config=None)
.. py:function:: paddle.fluid.dygraph.load_dygraph(model_path, config=None)
该接口用于从磁盘中加载Layer和Optimizer的 ``state_dict`` ,该接口会同时加载 ``model_path + ".pdparams"`` 和 ``model_path + ".pdopt"`` 中的内容。
.. note::
由于一些历史原因,如果从 ``paddle.io.save_inference_model`` 的存储结果中载入 ``state_dict`` ,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。
如果从 ``paddle.static.save_inference_model`` 的存储结果中载入 ``state_dict`` ,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。
参数:
- **model_path** (str) – 保存state_dict的文件前缀。该路径不应该包括后缀 ``.pdparams`` 或 ``.pdopt``。
- **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.io.save_inference_model`` 存储模型的格式。默认为 ``None``。
- **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.static.save_inference_model`` 存储模型的格式。默认为 ``None``。
返回: 两个 ``dict`` ,即从文件中恢复的模型参数 ``dict`` 和优化器参数 ``dict``,如果只找到其中一个的存储文件,另一个返回None
......@@ -29,13 +29,14 @@ load
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.disable_static()
emb = paddle.nn.Embedding([10, 10])
emb = paddle.nn.Embedding(10, 10)
state_dict = emb.state_dict()
paddle.save(state_dict, "paddle_dy")
fluid.save_dygraph(state_dict, "paddle_dy")
scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True)
......@@ -43,9 +44,9 @@ load
learning_rate=scheduler,
parameters=emb.parameters())
state_dict = adam.state_dict()
paddle.save(state_dict, "paddle_dy")
fluid.save_dygraph(state_dict, "paddle_dy")
para_state_dict, opti_state_dict = paddle.load("paddle_dy")
para_state_dict, opti_state_dict = fluid.load_dygraph("paddle_dy")
......@@ -5,7 +5,7 @@ SaveLoadConfig
.. py:class:: paddle.SaveLoadConfig()
用于配置接口 :ref:`cn_api_fluid_dygraph_jit_save` 和 :ref:`cn_api_fluid_dygraph_jit_load` 存储载入 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 时的附加选项。
用于配置接口 ``paddle.jit.save/load`` 和 ``paddle.load`` 存储载入时的附加选项。
**示例代码:**
......@@ -74,10 +74,10 @@ SaveLoadConfig
.. py:attribute:: output_spec
选择保存模型( :ref:`cn_api_fluid_dygraph_TranslatedLayer` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。
默认情况下,原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量都将配置为存储后模型 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 的输出变量。
选择保存模型( ``paddle.jit.TranslatedLayer`` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。
默认情况下,原始 ``paddle.nn.Layer`` 的forward方法的所有返回变量都将配置为存储后模型 ``paddle.jit.TranslatedLayer`` 的输出变量。
``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量,
``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 ``paddle.nn.Layer`` 的forward方法的所有返回变量,
将会依据输入的 ``output_spec`` 列表对存储的模型进行裁剪。
.. note::
......@@ -132,7 +132,7 @@ SaveLoadConfig
.. py:attribute:: model_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。
存储转写 ``paddle.nn.Layer`` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。
**示例代码**
.. code-block:: python
......@@ -183,7 +183,7 @@ SaveLoadConfig
.. py:attribute:: params_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。
存储转写 ``paddle.nn.Layer`` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。
**示例代码**
.. code-block:: python
......@@ -236,10 +236,13 @@ SaveLoadConfig
.. py:attribute:: separate_params
配置是否将 :ref:`cn_api_fluid_dygraph_Layer` 的参数存储为分散的文件。
(这是为了兼容接口 :ref:`cn_api_fluid_io_save_inference_model` 的行为)
(这是为了兼容接口 ``paddle.static.save_inference_model`` 的行为)
如果设置为 ``True`` ,每个参数将会被存储为一个文件,文件名为参数名,同时``SaveLoadConfig.params_filename`` 指定的文件名将不会生效。默认为 ``False``。
.. note::
仅用于 ``paddle.load`` 方法.
**示例代码**
.. code-block:: python
......@@ -273,7 +276,7 @@ SaveLoadConfig
adam.clear_grad()
model_path = "simplenet.example.model.separate_params"
config = paddle.jit.SaveLoadConfig()
config = paddle.SaveLoadConfig()
config.separate_params = True
# saving with configs.separate_params
......@@ -307,11 +310,11 @@ SaveLoadConfig
linear = paddle.nn.Linear(5, 1)
state_dict = linear.state_dict()
paddle.save(state_dict, "paddle_dy")
paddle.save(state_dict, "paddle_dy.pdparams")
configs = paddle.SaveLoadConfig()
configs.keep_name_table = True
para_state_dict, _ = paddle.load("paddle_dy", configs)
config = paddle.SaveLoadConfig()
config.keep_name_table = True
para_state_dict = paddle.load("paddle_dy.pdparams", config)
print(para_state_dict)
# the name_table is 'StructuredToParameterName@@'
......
......@@ -410,12 +410,12 @@ buffer是一个非参数类型的变量,不会被优化器更新,但在评
paddle.disable_static()
emb = paddle.nn.Embedding([10, 10])
emb = paddle.nn.Embedding(10, 10)
state_dict = emb.state_dict()
paddle.save(state_dict, "paddle_dy")
paddle.save(state_dict, "paddle_dy.pdparams")
para_state_dict, _ = paddle.load("paddle_dy")
para_state_dict = paddle.load("paddle_dy.pdparams")
emb.set_state_dict(para_state_dict)
.. _cn_api_fluid_dygraph_jit_load:
.. _cn_api_fluid_load:
load
-----------------
-------------------------------
.. py:function:: paddle.fluid.dygraph.jit.load(model_path, configs=None)
.. py:function:: paddle.fluid.load(program, model_path, executor=None, var_list=None)
:api_attr: 声明式编程模式(静态图)
将接口 :ref:`cn_api_fluid_dygraph_jit_save` 或者 :ref:`cn_api_fluid_io_save_inference_model` 存储的模型载入为 :ref:`cn_api_fluid_dygraph_TranslatedLayer` ,用于预测推理或者fine-tune训练。
.. note::
由于一些历史原因,如果载入的模型是通过 :ref:`cn_api_fluid_io_save_inference_model` 存储的,
在使用它进行fine-tune训练时会存在一些局限:
1. 命令式编程模式不支持 ``LoDTensor`` ,所有原先输入变量或者参数依赖于LoD信息的模型暂时无法使用;
2. 所有存储模型的feed变量都需要被传入 ``Translatedlayer`` 的forward方法;
3. 原模型变量的 ``stop_gradient`` 信息已丢失且无法准确恢复;
4. 原模型参数的 ``trainable`` 信息已丢失且无法准确恢复。
参数:
- **model_path** (str) - 存储模型的目录。
- **configs** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象。默认为 ``None``。
该接口从Program中过滤出参数和优化器信息,然后从文件中获取相应的值。
返回:TranslatedLayer - 一个能够执行存储模型的 ``Layer`` 对象
如果Program和加载的文件之间参数的维度或数据类型不匹配,将引发异常
**示例代码**
该函数还可以加载用[save_params,save_persistables,save_vars]接口保存的模型文件。
当[save_params,save_persistables,save_vars]保存的模型格式为单个大文件时,var_list不能为None。
1. 载入由接口 :ref:`cn_api_fluid_dygraph_jit_save` 存储的模型进行预测推理及fine-tune训练。
参数:
- **program** ( :ref:`cn_api_fluid_Program` ) – 要加载的Program。
- **model_path** (str) – 保存Program的目录名称+文件前缀。格式为 ``目录名称/文件前缀`` 。
- **executor** (Executor, 可选) - 当startup program没有运行时,用于初始化参数的Executor。默认值:None。
- **var_list** (list, 可选) - 指定加载的变量列表,该参数只在加载旧接口[save_params,save_persistables,save_vars]保存的模型文件时使用。当加载的是多个小文件时,变量列表可以是所有加载文件中变量的子集;当加载的单个大文件时,变量列表必须和加载文件中的变量保持一致。
.. code-block:: python
返回: 无
import numpy as np
**代码示例**
.. code-block:: python
# example1
import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
BATCH_SIZE = 32
BATCH_NUM = 20
def random_batch_reader():
def _get_random_images_and_labels(image_shape, label_shape):
image = np.random.random(size=image_shape).astype('float32')
label = np.random.random(size=label_shape).astype('int64')
return image, label
def __reader__():
for _ in range(BATCH_NUM):
batch_image, batch_label = _get_random_images_and_labels(
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label
return __reader__
class LinearNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(LinearNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
return self._linear(x)
# 开启命令式编程模式
fluid.enable_dygraph()
# 1. 训练存储模型.
# 创建网络
net = LinearNet(784, 1)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# 训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
net.clear_gradients()
model_path = "linear.example.model"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[img])
# 2. 载入模型 & 预测
# 载入模型
infer_net = fluid.dygraph.jit.load(model_path)
# 预测
x = fluid.dygraph.to_variable(np.random.random((1, 784)).astype('float32'))
pred = infer_net(x)
# 3. 载入模型 & fine-tune训练
# 载入模型
train_net = fluid.dygraph.jit.load(model_path)
train_net.train()
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=train_net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# fine-tune训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = train_net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
train_net.clear_gradients()
2. 载入由接口 :ref:`cn_api_fluid_io_save_inference_model` 存储的模型进行预测推理及fine-tune训练。
.. code-block:: python
import numpy as np
paddle.enable_static()
x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc(x, 10)
z = fluid.layers.fc(y, 10)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
fluid.save(fluid.default_main_program(), "./test_path")
fluid.load(fluid.default_main_program(), "./test_path")
# example2
# 注意example1和example2应该分开执行,避免干扰。
import paddle.fluid as fluid
BATCH_SIZE = 32
BATCH_NUM = 20
def random_batch_reader():
def _get_random_images_and_labels(image_shape, label_shape):
image = np.random.random(size=image_shape).astype('float32')
label = np.random.random(size=label_shape).astype('int64')
return image, label
def __reader__():
for _ in range(BATCH_NUM):
batch_image, batch_label = _get_random_images_and_labels(
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label
return __reader__
img = fluid.data(name='img', shape=[None, 784], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')
pred = fluid.layers.fc(input=img, size=10, act='softmax')
loss = fluid.layers.cross_entropy(input=pred, label=label)
avg_loss = fluid.layers.mean(loss)
optimizer = fluid.optimizer.SGD(learning_rate=0.001)
optimizer.minimize(avg_loss)
x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc(x, 10)
z = fluid.layers.fc(y, 10)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
loader = fluid.io.DataLoader.from_generator(
feed_list=[img, label], capacity=5, iterable=True)
loader.set_batch_generator(random_batch_reader(), places=place)
# 1. 训练 & 存储预测模型
for data in loader():
exe.run(
fluid.default_main_program(),
feed=data,
fetch_list=[avg_loss])
model_path = "fc.example.model"
fluid.io.save_inference_model(
model_path, ["img"], [pred], exe)
# 开启命令式编程模式
fluid.enable_dygraph()
# 2. 载入模型 & 预测
fc = fluid.dygraph.jit.load(model_path)
x = fluid.dygraph.to_variable(np.random.random((1, 784)).astype('float32'))
pred = fc(x)
# 3. 载入模型 & fine-tune训练
fc = fluid.dygraph.jit.load(model_path)
fc.train()
sgd = fluid.optimizer.SGD(learning_rate=0.001,
parameter_list=fc.parameters())
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(
random_batch_reader(), places=place)
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = fc(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
sgd.minimize(avg_loss)
fluid.save(fluid.default_main_program(), "./test_path")
fluid.load(fluid.default_main_program(), "./test_path", exe)
.. _cn_api_fluid_save:
save
-------------------------------
.. py:function:: paddle.fluid.save(program, model_path)
:api_attr: 声明式编程模式(静态图)
:alias_main: paddle.static.save
:alias: paddle.static.save
:old_api: paddle.fluid.save
该接口将传入的参数、优化器信息和网络描述保存到 ``model_path`` 。
参数包含所有的可训练 :ref:`cn_api_fluid_Variable` ,将保存到后缀为 ``.pdparams`` 的文件中。
优化器信息包含优化器使用的所有变量。对于Adam优化器,包含beta1、beta2、momentum等。
所有信息将保存到后缀为 ``.pdopt`` 的文件中。(如果优化器没有需要保存的变量(如sgd),则不会生成)。
网络描述是程序的描述。它只用于部署。描述将保存到后缀为 ``.pdmodel`` 的文件中。
参数:
- **program** ( :ref:`cn_api_fluid_Program` ) – 要保存的Program。
- **model_path** (str) – 保存program的文件前缀。格式为 ``目录名称/文件前缀``。如果文件前缀为空字符串,会引发异常。
返回: 无
**代码示例**
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data(name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc(x, 10)
z = fluid.layers.fc(y, 10)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
fluid.save(fluid.default_main_program(), "./test_path")
.. _cn_api_fluid_dygraph_jit_save:
save
-----------------
.. py:function:: paddle.fluid.dygraph.jit.save(layer, model_path, input_spec=None, configs=None)
将输入的经过 ``@declarative`` 装饰的 :ref:`cn_api_fluid_dygraph_Layer` 存储为 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 格式的模型,
载入后可用于预测推理或者fine-tune训练。
该接口将会将输入 :ref:`cn_api_fluid_dygraph_Layer` 转写后的模型结构 ``Program`` 和所有必要的持久参数变量存储至输入路径 ``model_path`` 中。
默认存储的 ``Program`` 文件名为 ``__model__``, 默认存储持久参数变量的文件名为 ``__variables__``,
同时会将变量的一些描述信息存储至文件 ``__variables.info__``,这些额外的信息将在fine-tune训练中使用。
存储的模型能够被以下API载入使用:
- :ref:`cn_api_fluid_dygraph_jit_load`
- :ref:`cn_api_fluid_io_load_inference_model` (需要配置参数 ``params_filename='__variables__'`` )
- 其他预测库API
参数:
- **layer** (Layer) - 需要存储的 :ref:`cn_api_fluid_dygraph_Layer` 对象。输入的 ``Layer`` 需要经过 ``@declarative`` 装饰。
- **model_path** (str) - 存储模型的目录。
- **input_spec** (list[Variable], 可选) - 描述存储模型的输入。此参数是传入当前存储的 ``TranslatedLayer`` forward方法的一个示例输入。如果为 ``None`` ,所有原 ``Layer`` forward方法的输入变量将都会被配置为存储模型的输入变量。默认为 ``None``。
- **configs** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象。默认为 ``None``。
返回:无
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
BATCH_SIZE = 32
BATCH_NUM = 20
def random_batch_reader():
def _get_random_images_and_labels(image_shape, label_shape):
image = np.random.random(size=image_shape).astype('float32')
label = np.random.random(size=label_shape).astype('int64')
return image, label
def __reader__():
for _ in range(BATCH_NUM):
batch_image, batch_label = _get_random_images_and_labels(
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label
return __reader__
class LinearNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(LinearNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
return self._linear(x)
# 开启命令式编程模式
fluid.enable_dygraph()
# 创建网络
net = LinearNet(784, 1)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# 训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
net.clear_gradients()
# 存储模型
model_path = "linear.example.model"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[img])
.. _cn_api_fluid_dygraph_jit_SaveLoadConfig:
SaveLoadConfig
-------------------------------
.. py:class:: paddle.fluid.dygraph.jit.SaveLoadConfig()
用于配置接口 :ref:`cn_api_fluid_dygraph_jit_save` 和 :ref:`cn_api_fluid_dygraph_jit_load` 存储载入 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 时的附加选项。
**示例代码:**
1. 在存储模型时使用 ``SaveLoadConfig``
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
# 在存储模型时使用SaveLoadConfig
model_path = "simplenet.example.model"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
2. 在载入模型时使用 ``SaveLoadConfig``
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
# 开启命令式编程模式
fluid.enable_dygraph()
# 在载入模型时使用SaveLoadconfig
model_path = "simplenet.example.model"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
# 预测
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
属性
::::::::::::
.. py:attribute:: output_spec
选择保存模型( :ref:`cn_api_fluid_dygraph_TranslatedLayer` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。
默认情况下,原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量都将配置为存储后模型 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 的输出变量。
``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量,
将会依据输入的 ``output_spec`` 列表对存储的模型进行裁剪。
.. note::
``output_spec`` 属性仅在存储模型时使用。
**示例代码:**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
loss = fluid.layers.mean(z)
return z, loss
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out, loss = net(x)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
# 使用SaveLoadconfig.output_spec
model_path = "simplenet.example.model.output_spec"
configs = fluid.dygraph.jit.SaveLoadConfig()
# 仅在存储模型中保留预测结果,丢弃loss
configs.output_spec = [out]
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
# 仅有预测结果输出
pred = infer_net(x)
.. py:attribute:: model_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.model_filename"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
# 配置configs.model_filename存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# __simplenet__ __variables__ __variables.info__
# 配置configs.model_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. py:attribute:: params_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.params_filename"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.params_filename = "__params__"
# 配置configs.params_filename存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# __model__ __params__ __variables.info__
# 配置configs.params_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. py:attribute:: separate_params
配置是否将 :ref:`cn_api_fluid_dygraph_Layer` 的参数存储为分散的文件。
(这是为了兼容接口 :ref:`cn_api_fluid_io_save_inference_model` 的行为)
如果设置为 ``True`` ,每个参数将会被存储为一个文件,文件名为参数名,同时``SaveLoadConfig.params_filename`` 指定的文件名将不会生效。默认为 ``False``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.separate_params"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.separate_params = True
# 配置configs.separate_params存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# linear_0.b_0 linear_0.w_0 __model__ __variables.info__
# 配置configs.params_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. _cn_api_paddle_framework_io_load:
load
-----
.. py:function:: paddle.load(path, config=None)
从指定路径载入可以在paddle中使用的对象实例。
.. note::
目前仅支持载入 Layer 或者 Optimizer 的 ``state_dict`` 。
.. note::
``paddle.load`` 支持从paddle1.x版本中静态图save相关API的存储结果中载入 ``state_dict`` 。 但是从``paddle.static.save_inference_model/paddle.fluid.io.save_params/paddle.fluid.io.save_persistables`` 等API的存储结果中载入 ``state_dict`` 时,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。
参数:
- **path** (str) – 载入目标对象实例的路径。通常该路径是目标文件的路径,在兼容载入 ``paddle.jit.save/paddle.static.save_inference_model`` 的存储结果时,该路径是一个目录。
- **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.jit.save/paddle.static.save_inference_model`` 存储结果的格式。默认为 ``None``。
返回: 一个可以在paddle中使用的对象实例
返回类型: Object
**代码示例**
.. code-block:: python
import paddle
paddle.disable_static()
emb = paddle.nn.Embedding(10, 10)
layer_state_dict = emb.state_dict()
paddle.save(layer_state_dict, "emb.pdparams")
scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True)
adam = paddle.optimizer.Adam(
learning_rate=scheduler,
parameters=emb.parameters())
opt_state_dict = adam.state_dict()
paddle.save(opt_state_dict, "adam.pdopt")
load_layer_state_dict = paddle.load("emb.pdparams")
load_opt_state_dict = paddle.load("adam.pdopt")
.. _cn_api_paddle_framework_io_save:
save
-----
.. py:function:: paddle.save(obj, model_path)
将对象实例obj保存到指定的路径中。
.. note::
目前仅支持存储 Layer 或者 Optimizer 的 ``state_dict`` 。
参数:
- **obj** (Object) – 要保存的对象实例。
- **path** (str) – 保存对象实例的路径。如果存储到当前路径,输入的path字符串将会作为保存的文件名。
返回: 无
**代码示例**
.. code-block:: python
import paddle
paddle.disable_static()
emb = paddle.nn.Embedding(10, 10)
layer_state_dict = emb.state_dict()
paddle.save(layer_state_dict, "emb.pdparams")
scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True)
adam = paddle.optimizer.Adam(
learning_rate=scheduler,
parameters=emb.parameters())
opt_state_dict = adam.state_dict()
paddle.save(opt_state_dict, "adam.pdopt")
......@@ -32,9 +32,12 @@ load_inference_model
.. code-block:: python
import paddle
import paddle.fluid as fluid
import numpy as np
paddle.enable_static()
# 构建模型
main_prog = fluid.Program()
startup_prog = fluid.Program()
......
......@@ -22,8 +22,11 @@ load_program_state
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc( x, 10)
z = fluid.layers.fc( y, 10)
......
......@@ -37,8 +37,11 @@ save_inference_model
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.enable_static()
path = "./infer_model"
# 用户定义网络,此处以softmax回归为例
......
......@@ -24,8 +24,11 @@ set_program_state
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc( x, 10)
z = fluid.layers.fc( y, 10)
......
......@@ -552,7 +552,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0])
# 声明式编程中需要使用执行器执行之前已经定义好的网络
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
# 声明式编程中需要调用执行器的run方法执行计算过程
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
```
......
......@@ -111,7 +111,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
......
......@@ -109,7 +109,7 @@ Load model and run it in static graph mode:
place = paddle.CPUPlace()
exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe)
program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance:
......
......@@ -25,16 +25,16 @@
.. image:: https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/paddle/guides/images/load_2.0.png?raw=true
1.2 静态图存储载入体系(飞桨框架1.x)
----------------------------
--------------------------------
静态图存储载入相关接口为飞桨框架1.x版本的主要使用接口,出于兼容性的目的,这些接口仍然可以在飞桨框架2.x使用,但不再推荐。相关接口包括:
- paddle.io.save
- paddle.io.load
- paddle.io.save_inference_model
- paddle.io.load_inference_model
- paddle.io.load_program_state
- paddle.io.set_program_state
- paddle.static.save
- paddle.static.load
- paddle.static.save_inference_model
- paddle.static.load_inference_model
- paddle.static.load_program_state
- paddle.static.set_program_state
由于飞桨框架2.0不再主推静态图模式,故本文不对以上主要用于飞桨框架1.x的相关接口展开介绍,如有需要,可以阅读对应API文档。
......@@ -45,7 +45,7 @@
- paddle.Model.save
- paddle.Model.load
飞桨框架2.0高阶API存储载入接口体系清晰,表意直观,若有需要,建议直接阅读相关API文档,此处不再赘述。
飞桨框架2.0高阶API仅有一套Save/Load接口,表意直观,体系清晰,若有需要,建议直接阅读相关API文档,此处不再赘述。
.. note::
本教程着重介绍飞桨框架2.x的各个存储载入接口的关系及各种使用场景,不对接口参数进行详细介绍,如果需要了解具体接口参数的含义,请直接阅读对应API文档。
......@@ -56,10 +56,7 @@
若仅需要存储/载入模型的参数,可以使用 ``paddle.save/load`` 结合Layer和Optimizer的state_dict达成目的,此处state_dict是对象的持久参数的载体,dict的key为参数名,value为参数真实的numpy array值。
2.1 参数存储
------------
参数存储时,先获取目标对象(Layer或者Optimzier)的state_dict,然后将state_dict存储至磁盘,示例如下:
结合以下简单示例,介绍参数存储和载入的方法,以下示例完成了一个简单网络的训练过程:
.. code-block:: python
......@@ -128,20 +125,53 @@
# train
train(layer, loader, loss_fn, adam)
# save
model_path = "linear_net"
param_state_dict = layer.state_dict()
paddle.save(param_state_dict, model_path)
2.1 参数存储
------------
参数存储时,先获取目标对象(Layer或者Optimzier)的state_dict,然后将state_dict存储至磁盘,示例如下(接前述示例):
opt_state_dict = adam.state_dict()
paddle.save(opt_state_dict, model_path)
.. code-block:: python
# save
paddle.save(layer.state_dict(), "linear_net.pdparams")
paddle.save(adam.state_dict(), "adam.pdopt")
2.2 参数载入
------------
参数载入时,先从磁盘载入保存的state_dict,然后通过set_state_dict方法配置到目标对象中,示例如下:
参数载入时,先从磁盘载入保存的state_dict,然后通过set_state_dict方法配置到目标对象中,示例如下(接前述示例):
.. code-block:: python
# load
layer_state_dict = paddle.load("linear_net.pdparams")
opt_state_dict = paddle.load("adam.pdopt")
layer.set_state_dict(layer_state_dict)
adam.set_state_dict(opt_state_dict)
三、模型&参数存储载入(训练部署)
############################
若要同时存储/载入模型结构和参数,可以使用 ``paddle.jit.save/load`` 实现。
3.1 模型&参数存储
----------------
模型&参数存储根据训练模式不同,有两种使用情况:
(1) 动转静训练 + 模型&参数存储
(2) 动态图训练 + 模型&参数存储
3.1.1 动转静训练 + 模型&参数存储
``````````````````````````````
动转静训练相比直接使用动态图训练具有更好的执行性能,训练完成后,直接将目标Layer传入 ``paddle.jit.save`` 存储即可。:
一个简单的网络训练示例如下:
.. code-block:: python
......@@ -175,6 +205,7 @@
super(LinearNet, self).__init__()
self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
@paddle.jit.to_static
def forward(self, x):
return self._linear(x)
......@@ -207,28 +238,20 @@
drop_last=True,
num_workers=2)
# load
model_path = "linear_net"
param_state_dict, opt_state_dict = paddle.load(model_path)
layer.set_state_dict(param_state_dict)
adam.set_state_dict(opt_state_dict)
# train
train(layer, loader, loss_fn, adam)
.. note::
``paddle.load`` 接口可能仍会改动,后续可能改为仅返回一个单独的dict。
三、模型&参数存储载入(训练部署)
############################
随后使用 ``paddle.jit.save`` 对模型和参数进行存储(接前述示例):
若要同时存储/载入模型结构和参数,可以使用 ``paddle.jit.save/load`` 实现。
.. code-block:: python
3.1 模型&参数存储
----------------
# save
model_path = "linear.example.model"
paddle.jit.save(layer, model_path)
同时存储模型和参数,需要结合动静转换功能使用。有以下三项注意点:
通过动转静训练后保存模型&参数,有以下两项注意点:
(1) Layer对象的forward方法需要经由 ``paddle.jit.to_static`` 装饰
......@@ -322,9 +345,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
return self._linear(x)
(3) 使用 ``paddle.jit.save`` 存储模型和参数
3.1.2 动态图训练 + 模型&参数存储
``````````````````````````````
动态图模式相比动转静模式更加便于调试,如果您仍需要使用动态图直接训练,也可以在动态图训练完成后调用 ``paddle.jit.save`` 直接存储模型和参数。
直接将目标Layer传入 ``paddle.jit.save`` 存储即可,完整示例如下
同样是一个简单的网络训练示例
.. code-block:: python
......@@ -332,6 +358,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
import paddle
import paddle.nn as nn
import paddle.optimizer as opt
from paddle.static import InputSpec
BATCH_SIZE = 16
BATCH_NUM = 4
......@@ -358,7 +385,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
super(LinearNet, self).__init__()
self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
@paddle.jit.to_static
def forward(self, x):
return self._linear(x)
......@@ -377,8 +403,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
place = paddle.CPUPlace()
paddle.disable_static(place)
# 1. train & save model.
# create network
layer = LinearNet()
loss_fn = nn.CrossEntropyLoss()
......@@ -396,14 +420,47 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# train
train(layer, loader, loss_fn, adam)
训练完成后使用 ``paddle.jit.save`` 对模型和参数进行存储:
.. code-block:: python
# save
model_path = "linear.example.model"
paddle.jit.save(layer, model_path)
model_path = "linear.example.dy_model"
paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[InputSpec(shape=[None, 784], dtype='float32')])
动态图训练后使用 ``paddle.jit.save`` 存储模型和参数注意点如下:
.. note::
后续仍会优化此处的使用方式,支持不装饰 ``to_static`` 也能够通过 ``paddle.jit.save`` 直接存储模型和参数。
(1) 相比动转静训练,Layer对象的forward方法不需要额外装饰,保持原实现即可
(2) 与动转静训练相同,请确保Layer.forward方法中仅实现预测功能,避免将训练所需的loss计算逻辑写入forward方法
(3) 在最后使用 ``paddle.jit.save`` 时,需要指定Layer的 ``InputSpec`` ,Layer对象forward方法的每一个参数均需要对应的 ``InputSpec`` 进行描述,不能省略。这里的 ``input_spec`` 参数支持两种类型的输入:
- ``InputSpec`` 列表
使用InputSpec描述forward输入参数的shape,dtype和name,如前述示例(此处示例中name省略,name省略的情况下会使用forward的对应参数名作为name,所以这里的name为 ``x`` ):
.. code-block:: python
paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[InputSpec(shape=[None, 784], dtype='float32')])
- Example Tensor 列表
除使用InputSpec之外,也可以直接使用forward训练时的示例输入,此处可以使用前述示例中迭代DataLoader得到的 ``image`` ,示例如下:
.. code-block:: python
paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[image])
3.2 模型&参数载入
----------------
......@@ -512,7 +569,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# load
model_path = "linear.example.model"
state_dict, _ = paddle.load(model_path)
state_dict = paddle.load(model_path)
# inference
layer.set_state_dict(state_dict, use_structured_name=False)
......@@ -526,7 +583,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
如果您是从飞桨框架1.x切换到2.x,曾经使用飞桨框架1.x的接口存储模型或者参数,飞桨框架2.x也对这种情况进行了兼容性支持,包括以下几种情况。
4.1 从 ``paddle.io.save_inference_model`` 存储结果中载入模型&参数
4.1 从 ``paddle.static.save_inference_model`` 存储结果中载入模型&参数
------------------------------------------------------------------
曾用接口名为 ``paddle.fluid.io.save_inference_model`` 。
......@@ -535,7 +592,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
使用 ``paddle.jit.load`` 配合 ``paddle.SaveLoadConfig`` 载入模型和参数。
模型准备及训练示例,该示例为后续所有示例的前序逻辑:
飞桨1.x模型准备及训练示例,该示例为后续所有示例的前序逻辑:
.. code-block:: python
......@@ -670,7 +727,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
model_path = "fc.example.model"
load_param_dict, _ = paddle.load(model_path)
load_param_dict = paddle.load(model_path)
如果您指定了存储的模型文件名,可以按照以下方式载入(接前述示例):
......@@ -680,7 +737,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
config = paddle.SaveLoadConfig()
config.model_filename = "__simplenet__"
load_param_dict, _ = paddle.load(model_path, config)
load_param_dict = paddle.load(model_path, config)
如果您指定了存储的参数文件名,可以按照以下方式载入(接前述示例):
......@@ -690,7 +747,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
config = paddle.SaveLoadConfig()
config.params_filename = "__params__"
load_param_dict, _ = paddle.load(model_path, config)
load_param_dict = paddle.load(model_path, config)
.. note::
一般预测模型不会存储优化器Optimizer的参数,因此此处载入的仅包括模型本身的参数。
......@@ -698,12 +755,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
.. note::
由于 ``structured_name`` 是动态图下独有的变量命名方式,因此从静态图存储结果载入的state_dict在配置到动态图的Layer中时,需要配置 ``Layer.set_state_dict(use_structured_name=False)`` 。
4.2 从 ``paddle.io.save`` 存储结果中载入参数
4.2 从 ``paddle.static.save`` 存储结果中载入参数
----------------------------------------------
曾用接口名为 ``paddle.fluid.save`` 。
``paddle.fluid.save`` 的存储格式与2.x动态图接口 ``paddle.save`` 存储格式是类似的,同样存储了dict格式的参数,因此可以直接使用 ``paddle.load`` 载入state_dict,示例如下(接前述示例):
``paddle.fluid.save`` 的存储格式与2.x动态图接口 ``paddle.save`` 存储格式是类似的,同样存储了dict格式的参数,因此可以直接使用 ``paddle.load`` 载入state_dict,但需要注意不能仅传入保存的路径,而要传入保存参数的文件名,示例如下(接前述示例):
.. code-block:: python
......@@ -715,22 +772,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# enable dygraph mode
paddle.disable_static(place)
load_param_dict, _ = paddle.load(model_path)
load_param_dict = paddle.load("fc.example.model.save.pdparams")
.. note::
由于 ``paddle.fluid.save`` 接口原先在静态图模式下的定位是存储训练时参数,或者说存储Checkpoint,故尽管其同时存储了模型结构,目前也暂不支持从 ``paddle.fluid.save`` 的存储结果中同时载入模型和参数,后续如有需求再考虑支持。
4.3 从 ``paddle.io.save_params/save_persistables`` 存储结果中载入参数
-----------------------------------------------------------------------
4.3 从 ``paddle.fluid.io.save_params/save_persistables`` 存储结果中载入参数
-------------------------------------------------------------------------
.. note::
以下方式仅为暂时解决方案,后续计划会在 ``paddle.load`` 接口支持此功能。
这两个接口在飞桨1.x版本时,已经不再推荐作为存储模型参数的接口使用,故并未继承至飞桨2.x,之后也不会再推荐使用这两个接口存储参数。
对于使用这两个接口存储参数兼容载入的支持,分为两种情况,下面以 ``paddle.fluid.io.save_params`` 接口为例介绍相关使用方法:
曾用接口名为 ``paddle.fluid.io.save_params/save_persistables`` 。
(1) 使用默认方式存储,各参数分散存储为单独的文件,文件名为参数名
此处可以使用 ``paddle.io.load_program_state`` 接口从以上两个接口的存储结果中载入state_dict,并用于动态图Layer的配置,示例如下(接前述示例):
这种存储方式仍然可以使用 ``paddle.load`` 接口兼容载入,使用示例如下(接前述示例):
.. code-block:: python
......@@ -739,4 +797,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
fluid.io.save_params(exe, model_path)
# load
state_dict = paddle.io.load_program_state(model_path)
state_dict = paddle.load(model_path)
print(state_dict)
(2) 指定了参数存储的文件,将所有参数存储至单个文件中
将所有参数存储至单个文件中会导致存储结果中丢失Tensor名和Tensor数据之间的映射关系,因此这部分丢失的信息需要用户传入进行补足。为了确保正确性,这里不仅要传入Tensor的name列表,同时要传入Tensor的shape和dtype等描述信息,通过检查和存储数据的匹配性确保严格的正确性,这导致载入数据的恢复过程变得比较复杂,仍然需要一些飞桨1.x的概念支持。后续如果此项需求较为普遍,我们将会考虑将该项功能兼容支持到 ``paddle.load`` 中,但由于信息丢失而导致的使用复杂性仍然是存在的,因此建议您避免仅使用这两个接口存储参数。
目前暂时推荐您使用 ``paddle.static.load_program_state`` 接口解决此处的载入问题,需要获取原Program中的参数列表传入该方法,使用示例如下(接前述示例):
.. code-block:: python
# save by fluid.io.save_params
model_path = "fc.example.model.save_params_with_filename"
fluid.io.save_params(exe, model_path, filename="__params__")
# load
import os
params_file_path = os.path.join(model_path, "__params__")
var_list = fluid.default_main_program().all_parameters()
state_dict = paddle.io.load_program_state(params_file_path, var_list)
......@@ -173,8 +173,8 @@
"#### paddle 基础框架-动态图-模型参数保存 \n",
" * paddle.save\n",
"#### paddle 基础框架-静态图-模型参数保存 \n",
" * paddle.io.save\n",
" * paddle.io.save_inference_model\n",
" * paddle.static.save\n",
" * paddle.static.save_inference_model\n",
"\n",
"下面将基于高阶API对模型保存与加载的方法进行讲解。"
]
......@@ -230,8 +230,8 @@
"#### paddle 基础框架-动态图-模型参数加载\n",
" * paddle.load\n",
"#### paddle 基础框架-静态图-模型参数加载\n",
" * paddle.io.load \n",
" * paddle.io.load_inference_model"
" * paddle.static.load \n",
" * paddle.static.load_inference_model"
]
},
{
......
......@@ -127,8 +127,8 @@ import MNIST 引入即可。
目前Paddle框架有三种保存模型参数的体系,分别是: #### paddle
高阶API-模型参数保存 \* paddle.Model.fit \* paddle.Model.save ####
paddle 基础框架-动态图-模型参数保存 \* paddle.save #### paddle
基础框架-静态图-模型参数保存 \* paddle.io.save \*
paddle.io.save_inference_model
基础框架-静态图-模型参数保存 \* paddle.static.save \*
paddle.static.save_inference_model
下面将基于高阶API对模型保存与加载的方法进行讲解。
......@@ -168,8 +168,8 @@ paddle.io.save_inference_model
当恢复训练状态时,需要加载模型数据,此时我们可以使用加载函数从存储模型状态和优化器状态的文件中载入模型参数和优化器参数,如果不需要恢复优化器,则不必使用优化器状态文件。
#### 高阶API-模型参数加载 \* paddle.Model.load #### paddle
基础框架-动态图-模型参数加载 \* paddle.load #### paddle
基础框架-静态图-模型参数加载 \* paddle.io.load \*
paddle.io.load_inference_model
基础框架-静态图-模型参数加载 \* paddle.static.load \*
paddle.static.load_inference_model
下面将对高阶API的模型参数加载方法进行讲解 \* model.load(self, path,
skip_mismatch=False, reset_optimizer=False)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册