From 4f6c833d903f00f3b4b9de85aad61b3fad86fdcb Mon Sep 17 00:00:00 2001 From: Chen Weihang Date: Thu, 24 Sep 2020 16:01:46 +0800 Subject: [PATCH] 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 --- .../program_translator_cn.rst | 2 +- .../program_translator_en.rst | 2 +- doc/fluid/api_cn/fluid_cn/save_cn.rst | 4 +- doc/fluid/api_cn/io_cn/load_cn.rst | 4 +- doc/fluid/beginners_guide/dygraph/DyGraph.md | 2 +- doc/paddle/api/alias_api_mapping | 8 +- .../dygraph/checkpoint/load_dygraph_cn.rst | 17 +- .../fluid/dygraph/jit/SaveLoadConfig_cn.rst | 27 +- .../paddle/fluid/dygraph/layers/Layer_cn.rst | 6 +- doc/paddle/api/paddle/fluid/io/load_cn.rst | 221 ++++---------- doc/paddle/api/paddle/fluid/io/save_cn.rst | 54 ++++ doc/paddle/api/paddle/fluid/save_cn.rst | 80 ----- .../paddle/framework/SaveLoadConfig_cn.rst | 273 ------------------ .../api/paddle/framework/io/load_cn.rst | 46 +++ .../api/paddle/framework/io/save_cn.rst | 37 +++ .../load_inference_model_cn.rst | 3 + .../{io => static}/load_program_state_cn.rst | 3 + .../save_inference_model_cn.rst | 3 + .../{io => static}/set_program_state_cn.rst | 3 + doc/paddle/beginners_guide/dygraph/DyGraph.md | 2 +- .../dygraph_to_static/basic_usage_cn.rst | 2 +- .../dygraph_to_static/basic_usage_en.rst | 2 +- doc/paddle/guides/model_save_load_cn.rst | 195 +++++++++---- .../quick_start/save_model/save_model.ipynb | 8 +- .../quick_start/save_model/save_model.rst | 8 +- 25 files changed, 390 insertions(+), 622 deletions(-) create mode 100644 doc/paddle/api/paddle/fluid/io/save_cn.rst delete mode 100644 doc/paddle/api/paddle/fluid/save_cn.rst delete mode 100644 doc/paddle/api/paddle/framework/SaveLoadConfig_cn.rst create mode 100644 doc/paddle/api/paddle/framework/io/load_cn.rst create mode 100644 doc/paddle/api/paddle/framework/io/save_cn.rst rename doc/paddle/api/paddle/{io => static}/load_inference_model_cn.rst (98%) rename doc/paddle/api/paddle/{io => static}/load_program_state_cn.rst (96%) rename doc/paddle/api/paddle/{io => static}/save_inference_model_cn.rst (98%) rename doc/paddle/api/paddle/{io => static}/set_program_state_cn.rst (96%) diff --git a/doc/fluid/advanced_guide/dygraph_to_static/program_translator_cn.rst b/doc/fluid/advanced_guide/dygraph_to_static/program_translator_cn.rst index 03852fc58..208fab9d1 100644 --- a/doc/fluid/advanced_guide/dygraph_to_static/program_translator_cn.rst +++ b/doc/fluid/advanced_guide/dygraph_to_static/program_translator_cn.rst @@ -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) diff --git a/doc/fluid/advanced_guide/dygraph_to_static/program_translator_en.rst b/doc/fluid/advanced_guide/dygraph_to_static/program_translator_en.rst index 573ddbb79..60a204729 100644 --- a/doc/fluid/advanced_guide/dygraph_to_static/program_translator_en.rst +++ b/doc/fluid/advanced_guide/dygraph_to_static/program_translator_en.rst @@ -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: diff --git a/doc/fluid/api_cn/fluid_cn/save_cn.rst b/doc/fluid/api_cn/fluid_cn/save_cn.rst index a15b23f2b..ab1f63e8c 100644 --- a/doc/fluid/api_cn/fluid_cn/save_cn.rst +++ b/doc/fluid/api_cn/fluid_cn/save_cn.rst @@ -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 diff --git a/doc/fluid/api_cn/io_cn/load_cn.rst b/doc/fluid/api_cn/io_cn/load_cn.rst index 863dd4ea0..1a8e78f99 100644 --- a/doc/fluid/api_cn/io_cn/load_cn.rst +++ b/doc/fluid/api_cn/io_cn/load_cn.rst @@ -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 diff --git a/doc/fluid/beginners_guide/dygraph/DyGraph.md b/doc/fluid/beginners_guide/dygraph/DyGraph.md index 6d1089d50..d71c7bbfb 100644 --- a/doc/fluid/beginners_guide/dygraph/DyGraph.md +++ b/doc/fluid/beginners_guide/dygraph/DyGraph.md @@ -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) ``` diff --git a/doc/paddle/api/alias_api_mapping b/doc/paddle/api/alias_api_mapping index 2b2b4074e..a29a76ae8 100644 --- a/doc/paddle/api/alias_api_mapping +++ b/doc/paddle/api/alias_api_mapping @@ -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 diff --git a/doc/paddle/api/paddle/fluid/dygraph/checkpoint/load_dygraph_cn.rst b/doc/paddle/api/paddle/fluid/dygraph/checkpoint/load_dygraph_cn.rst index a49c06ac7..289322788 100644 --- a/doc/paddle/api/paddle/fluid/dygraph/checkpoint/load_dygraph_cn.rst +++ b/doc/paddle/api/paddle/fluid/dygraph/checkpoint/load_dygraph_cn.rst @@ -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") diff --git a/doc/paddle/api/paddle/fluid/dygraph/jit/SaveLoadConfig_cn.rst b/doc/paddle/api/paddle/fluid/dygraph/jit/SaveLoadConfig_cn.rst index 9cf216513..3610fefd1 100644 --- a/doc/paddle/api/paddle/fluid/dygraph/jit/SaveLoadConfig_cn.rst +++ b/doc/paddle/api/paddle/fluid/dygraph/jit/SaveLoadConfig_cn.rst @@ -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@@' diff --git a/doc/paddle/api/paddle/fluid/dygraph/layers/Layer_cn.rst b/doc/paddle/api/paddle/fluid/dygraph/layers/Layer_cn.rst index ffb30530b..ac5d8c3e5 100644 --- a/doc/paddle/api/paddle/fluid/dygraph/layers/Layer_cn.rst +++ b/doc/paddle/api/paddle/fluid/dygraph/layers/Layer_cn.rst @@ -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) diff --git a/doc/paddle/api/paddle/fluid/io/load_cn.rst b/doc/paddle/api/paddle/fluid/io/load_cn.rst index 36f03340e..22cf7593e 100644 --- a/doc/paddle/api/paddle/fluid/io/load_cn.rst +++ b/doc/paddle/api/paddle/fluid/io/load_cn.rst @@ -1,167 +1,58 @@ -.. _cn_api_fluid_dygraph_jit_load: +.. _cn_api_fluid_load: load ------------------ - -.. py:function:: paddle.fluid.dygraph.jit.load(model_path, configs=None) - - -将接口 :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``。 - -返回:TranslatedLayer - 一个能够执行存储模型的 ``Layer`` 对象。 - -**示例代码** - -1. 载入由接口 :ref:`cn_api_fluid_dygraph_jit_save` 存储的模型进行预测推理及fine-tune训练。 - - .. 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() - # 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 - 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) - 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) +------------------------------- + +.. py:function:: paddle.fluid.load(program, model_path, executor=None, var_list=None) + +:api_attr: 声明式编程模式(静态图) + + + +该接口从Program中过滤出参数和优化器信息,然后从文件中获取相应的值。 + +如果Program和加载的文件之间参数的维度或数据类型不匹配,将引发异常。 + +该函数还可以加载用[save_params,save_persistables,save_vars]接口保存的模型文件。 +当[save_params,save_persistables,save_vars]保存的模型格式为单个大文件时,var_list不能为None。 + +参数: + - **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 + + # example1 + 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") + fluid.load(fluid.default_main_program(), "./test_path") + + # example2 + # 注意example1和example2应该分开执行,避免干扰。 + import paddle.fluid as fluid + + 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", exe) + diff --git a/doc/paddle/api/paddle/fluid/io/save_cn.rst b/doc/paddle/api/paddle/fluid/io/save_cn.rst new file mode 100644 index 000000000..6fe19e65e --- /dev/null +++ b/doc/paddle/api/paddle/fluid/io/save_cn.rst @@ -0,0 +1,54 @@ +.. _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") + + + + + + + diff --git a/doc/paddle/api/paddle/fluid/save_cn.rst b/doc/paddle/api/paddle/fluid/save_cn.rst deleted file mode 100644 index f0276316b..000000000 --- a/doc/paddle/api/paddle/fluid/save_cn.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. _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]) diff --git a/doc/paddle/api/paddle/framework/SaveLoadConfig_cn.rst b/doc/paddle/api/paddle/framework/SaveLoadConfig_cn.rst deleted file mode 100644 index cbee1bab2..000000000 --- a/doc/paddle/api/paddle/framework/SaveLoadConfig_cn.rst +++ /dev/null @@ -1,273 +0,0 @@ -.. _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) diff --git a/doc/paddle/api/paddle/framework/io/load_cn.rst b/doc/paddle/api/paddle/framework/io/load_cn.rst new file mode 100644 index 000000000..e10d22235 --- /dev/null +++ b/doc/paddle/api/paddle/framework/io/load_cn.rst @@ -0,0 +1,46 @@ +.. _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") diff --git a/doc/paddle/api/paddle/framework/io/save_cn.rst b/doc/paddle/api/paddle/framework/io/save_cn.rst new file mode 100644 index 000000000..b3a450f4a --- /dev/null +++ b/doc/paddle/api/paddle/framework/io/save_cn.rst @@ -0,0 +1,37 @@ +.. _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") diff --git a/doc/paddle/api/paddle/io/load_inference_model_cn.rst b/doc/paddle/api/paddle/static/load_inference_model_cn.rst similarity index 98% rename from doc/paddle/api/paddle/io/load_inference_model_cn.rst rename to doc/paddle/api/paddle/static/load_inference_model_cn.rst index 17210d8b2..6cc889f2b 100644 --- a/doc/paddle/api/paddle/io/load_inference_model_cn.rst +++ b/doc/paddle/api/paddle/static/load_inference_model_cn.rst @@ -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() diff --git a/doc/paddle/api/paddle/io/load_program_state_cn.rst b/doc/paddle/api/paddle/static/load_program_state_cn.rst similarity index 96% rename from doc/paddle/api/paddle/io/load_program_state_cn.rst rename to doc/paddle/api/paddle/static/load_program_state_cn.rst index 9875b5406..bafcdb38b 100644 --- a/doc/paddle/api/paddle/io/load_program_state_cn.rst +++ b/doc/paddle/api/paddle/static/load_program_state_cn.rst @@ -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) diff --git a/doc/paddle/api/paddle/io/save_inference_model_cn.rst b/doc/paddle/api/paddle/static/save_inference_model_cn.rst similarity index 98% rename from doc/paddle/api/paddle/io/save_inference_model_cn.rst rename to doc/paddle/api/paddle/static/save_inference_model_cn.rst index 9a4b7a3d2..1e24e5249 100644 --- a/doc/paddle/api/paddle/io/save_inference_model_cn.rst +++ b/doc/paddle/api/paddle/static/save_inference_model_cn.rst @@ -37,8 +37,11 @@ save_inference_model .. code-block:: python + import paddle import paddle.fluid as fluid + paddle.enable_static() + path = "./infer_model" # 用户定义网络,此处以softmax回归为例 diff --git a/doc/paddle/api/paddle/io/set_program_state_cn.rst b/doc/paddle/api/paddle/static/set_program_state_cn.rst similarity index 96% rename from doc/paddle/api/paddle/io/set_program_state_cn.rst rename to doc/paddle/api/paddle/static/set_program_state_cn.rst index a2510b9d8..5cd9f7901 100644 --- a/doc/paddle/api/paddle/io/set_program_state_cn.rst +++ b/doc/paddle/api/paddle/static/set_program_state_cn.rst @@ -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) diff --git a/doc/paddle/beginners_guide/dygraph/DyGraph.md b/doc/paddle/beginners_guide/dygraph/DyGraph.md index 2e0d095ad..29dbb786d 100644 --- a/doc/paddle/beginners_guide/dygraph/DyGraph.md +++ b/doc/paddle/beginners_guide/dygraph/DyGraph.md @@ -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) ``` diff --git a/doc/paddle/guides/dygraph_to_static/basic_usage_cn.rst b/doc/paddle/guides/dygraph_to_static/basic_usage_cn.rst index 1a249870e..ac6390889 100644 --- a/doc/paddle/guides/dygraph_to_static/basic_usage_cn.rst +++ b/doc/paddle/guides/dygraph_to_static/basic_usage_cn.rst @@ -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) diff --git a/doc/paddle/guides/dygraph_to_static/basic_usage_en.rst b/doc/paddle/guides/dygraph_to_static/basic_usage_en.rst index f8b30dd74..ca3bf099f 100644 --- a/doc/paddle/guides/dygraph_to_static/basic_usage_en.rst +++ b/doc/paddle/guides/dygraph_to_static/basic_usage_en.rst @@ -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: diff --git a/doc/paddle/guides/model_save_load_cn.rst b/doc/paddle/guides/model_save_load_cn.rst index 73d0f0072..8f6273d36 100644 --- a/doc/paddle/guides/model_save_load_cn.rst +++ b/doc/paddle/guides/model_save_load_cn.rst @@ -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) diff --git a/doc/paddle/tutorial/quick_start/save_model/save_model.ipynb b/doc/paddle/tutorial/quick_start/save_model/save_model.ipynb index 812d26318..8c3d9e2c3 100644 --- a/doc/paddle/tutorial/quick_start/save_model/save_model.ipynb +++ b/doc/paddle/tutorial/quick_start/save_model/save_model.ipynb @@ -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" ] }, { diff --git a/doc/paddle/tutorial/quick_start/save_model/save_model.rst b/doc/paddle/tutorial/quick_start/save_model/save_model.rst index 91a6b2175..d5e1aae41 100644 --- a/doc/paddle/tutorial/quick_start/save_model/save_model.rst +++ b/doc/paddle/tutorial/quick_start/save_model/save_model.rst @@ -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) -- GitLab