diff --git a/doc/paddle/api/paddle/fluid/dygraph/jit/save_cn.rst b/doc/paddle/api/paddle/fluid/dygraph/jit/save_cn.rst index 51e8f2e503e..e3f7ec37707 100644 --- a/doc/paddle/api/paddle/fluid/dygraph/jit/save_cn.rst +++ b/doc/paddle/api/paddle/fluid/dygraph/jit/save_cn.rst @@ -5,7 +5,7 @@ save .. py:function:: paddle.jit.save(layer, path, input_spec=None, **configs) -将输入的 ``Layer`` 存储为 ``paddle.jit.TranslatedLayer`` 格式的模型,载入后可用于预测推理或者fine-tune训练。 +将输入的 ``Layer`` 或 ``function`` 存储为 ``paddle.jit.TranslatedLayer`` 格式的模型,载入后可用于预测推理或者fine-tune训练。 该接口会将输入 ``Layer`` 转写后的模型结构 ``Program`` 和所有必要的持久参数变量存储至输入路径 ``path`` 。 @@ -16,9 +16,12 @@ save - ``paddle.static.load_inference_model`` - 其他预测库API +.. note:: + 当使用 ``paddle.jit.save`` 保存 ``function`` 时, ``function`` 不能包含参数变量。如果必须保存参数变量,请用Layer封装function,然后按照处理Layer的方式调用相应的API。 + 参数 ::::::::: - - layer (Layer) - 需要存储的 ``Layer`` 对象。 + - layer (Layer|function) - 需要存储的 ``Layer`` 对象或者 ``function``。 - path (str) - 存储模型的路径前缀。格式为 ``dirname/file_prefix`` 或者 ``file_prefix`` 。 - input_spec (list[InputSpec|Tensor], 可选) - 描述存储模型forward方法的输入,可以通过InputSpec或者示例Tensor进行描述。如果为 ``None`` ,所有原 ``Layer`` forward方法的输入变量将都会被配置为存储模型的输入变量。默认为 ``None``。 - **configs (dict, 可选) - 其他用于兼容的存储配置选项。这些选项将来可能被移除,如果不是必须使用,不推荐使用这些配置选项。默认为 ``None``。目前支持以下配置选项:(1) output_spec (list[Tensor]) - 选择存储模型的输出目标。默认情况下,所有原 ``Layer`` forward方法的返回值均会作为存储模型的输出。如果传入的 ``output_spec`` 列表不是所有的输出变量,存储的模型将会根据 ``output_spec`` 所包含的结果被裁剪。 @@ -32,6 +35,7 @@ save .. code-block:: python + # example 1: save layer import numpy as np import paddle import paddle.nn as nn @@ -98,3 +102,25 @@ save # save path = "example_model/linear" paddle.jit.save(layer, path) + + # example 2: save function + import paddle + from paddle.static import InputSpec + + + def save_function(): + @paddle.jit.to_static + def fun(inputs): + return paddle.tanh(inputs) + + path = 'test_jit_save_load_function_1/func' + inps = paddle.rand([3, 6]) + origin = fun(inps) + + paddle.jit.save(fun, path) + load_func = paddle.jit.load(path) + + load_result = load_func(inps) + print((load_result - origin).abs().max() < 1e-10) + + save_function() diff --git a/doc/paddle/api/paddle/fluid/framework/Program_cn.rst b/doc/paddle/api/paddle/fluid/framework/Program_cn.rst index a74359ae148..e24ebf87404 100644 --- a/doc/paddle/api/paddle/fluid/framework/Program_cn.rst +++ b/doc/paddle/api/paddle/fluid/framework/Program_cn.rst @@ -469,3 +469,75 @@ list[ :ref:`api_guide_parameter` ],一个包含当前Program中所有参数的 # Here print(param) will print out all the properties of a parameter, # including name, type and persistable, you can access to specific # property of a parameter, such as param.name, param.type + +.. py:method:: state_dict(mode='all', scope=None) + +获取当前 ``Program`` 持久性变量。并将所有持久性变量存放在dict结构中。 + +参数 +::::::::: + - mode (str, 可选) - 获取何种持久性变量。目前支持以下选项: (1) 'opt':获得优化器的持久性变量放在dict结构中; (2) 'param':获得组网中的持久性变量放在dict结构中,不包含优化器中的持久性变量; (3) 'all':获得组网和优化器中的持久性变量放在dict结构中;默认值为'all'。 + - scope (Scope, 可选) - 如果scope为 ``None`` ,通过 `paddle.static.global_scope()` 获取全局/默认作用域实例,并从中获取 ``state_dict`` ;否则从指定的 ``scope`` 获取 ``state_dict`` 。默认值为 ``None`` 。 + +返回 +::::::::: +dict, 包含持久性变量的dict,键值是持久性变量的名字,值为持久性变量。 + +代码示例 +::::::::: + +.. code-block:: python + + import paddle + import paddle.static as static + + paddle.enable_static() + + x = static.data(name="x", shape=[10, 10], dtype='float32') + y = static.nn.fc(x, 10) + z = static.nn.fc(y, 10) + + place = paddle.CPUPlace() + exe = static.Executor(place) + exe.run(static.default_startup_program()) + prog = static.default_main_program() + + path = "./temp/model.pdparams" + paddle.save(prog.state_dict(), path) + +.. py:method:: set_state_dict(state_dict, scope=None) + +将 ``state_dict`` 中的持久性变量设置到 ``Program`` 中。 + +参数 +::::::::: + - state_dict (dict) - 包含持久性变量的字典。键值是持久性变量的名字,值为持久性变量。 + - scope (Scope, 可选) - 如果scope为 ``None`` ,通过 `paddle.static.global_scope()` 获取全局/默认作用域实例,并将 ``state_dict`` 中久性变量设置到这个作用域中;否则将 ``state_dict`` 设置到指定的 ``scope`` 中。默认值为 ``None`` 。 + +返回 +::::::::: +None + +代码示例 +::::::::: + +.. code-block:: python + + import paddle + import paddle.static as static + + paddle.enable_static() + + x = static.data(name="x", shape=[10, 10], dtype='float32') + y = static.nn.fc(x, 10) + z = static.nn.fc(y, 10) + + place = paddle.CPUPlace() + exe = static.Executor(place) + exe.run(static.default_startup_program()) + prog = static.default_main_program() + + path = "./temp/model.pdparams" + paddle.save(prog.state_dict(), path) + state_dict_load = paddle.load(path) + prog.set_state_dict(state_dict_load) diff --git a/doc/paddle/api/paddle/fluid/framework/Variable_cn.rst b/doc/paddle/api/paddle/fluid/framework/Variable_cn.rst index b3d76960758..fe414142732 100644 --- a/doc/paddle/api/paddle/fluid/framework/Variable_cn.rst +++ b/doc/paddle/api/paddle/fluid/framework/Variable_cn.rst @@ -114,6 +114,95 @@ Variable print("new var's dtype is: {}".format(new_variable.dtype)) +.. py:method:: get_value(scope=None) + +获取 :ref:`api_guide_Variable` 的值。 + +参数 +::::::::: + - scope ( Scope,可选 ) - 从指定的 ``scope`` 中获取 :ref:`api_guide_Variable` 的值。如果 ``scope`` 为 ``None`` ,通过 `paddle.static.global_scope()` 获取全局/默认作用域实例,并从中获取 :ref:`api_guide_Variable` 的值;否则,从指定的 ``scope`` 中获取 :ref:`api_guide_Variable` 的值。 + +返回 +::::::::: +Tensor, :ref:`api_guide_Variable` 的值 + +代码示例 +:::::::::: + +.. code-block:: python + + import paddle + import paddle.static as static + import numpy as np + + paddle.enable_static() + + x = static.data(name="x", shape=[10, 10], dtype='float32') + + y = static.nn.fc(x, 10, name='fc') + place = paddle.CPUPlace() + exe = static.Executor(place) + prog = paddle.static.default_main_program() + exe.run(static.default_startup_program()) + inputs = np.ones((10, 10), dtype='float32') + exe.run(prog, feed={'x': inputs}, fetch_list=[y, ]) + path = 'temp/tensor_' + for var in prog.list_vars(): + if var.persistable: + t = var.get_value() + paddle.save(t, path+var.name+'.pdtensor') + + for var in prog.list_vars(): + if var.persistable: + t_load = paddle.load(path+var.name+'.pdtensor') + var.set_value(t_load) + + +.. py:method:: set_value(value, scope=None) + +将 ``value`` 设置为 :ref:`api_guide_Variable` 的值。 + +参数 +::::::::: + - value ( Tensor|ndarray ) - :ref:`api_guide_Variable` 的值。 + - scope ( Scope,可选 ) - 将 :ref:`api_guide_Variable` 的值设置到指定的 ``scope`` 中。如果 ``scope`` 为 ``None`` ,通过 `paddle.static.global_scope()` 获取全局/默认作用域实例,并将 :ref:`api_guide_Variable` 的值设置到这个用域实例中;否则,将 :ref:`api_guide_Variable` 的值设置到指定的 ``scope`` 中。 + +返回 +::::::::: +None + +代码示例 +:::::::::: + +.. code-block:: python + + import paddle + import paddle.static as static + import numpy as np + + paddle.enable_static() + + x = static.data(name="x", shape=[10, 10], dtype='float32') + + y = static.nn.fc(x, 10, name='fc') + place = paddle.CPUPlace() + exe = static.Executor(place) + prog = paddle.static.default_main_program() + exe.run(static.default_startup_program()) + inputs = np.ones((10, 10), dtype='float32') + exe.run(prog, feed={'x': inputs}, fetch_list=[y, ]) + path = 'temp/tensor_' + for var in prog.list_vars(): + if var.persistable: + t = var.get_value() + paddle.save(t, path+var.name+'.pdtensor') + + for var in prog.list_vars(): + if var.persistable: + t_load = paddle.load(path+var.name+'.pdtensor') + var.set_value(t_load) + + 属性 :::::::::::: diff --git a/doc/paddle/api/paddle/fluid/io/save_cn.rst b/doc/paddle/api/paddle/fluid/io/save_cn.rst index ef8c5691563..5b18a924c98 100644 --- a/doc/paddle/api/paddle/fluid/io/save_cn.rst +++ b/doc/paddle/api/paddle/fluid/io/save_cn.rst @@ -3,7 +3,7 @@ save ------------------------------- -.. py:function:: paddle.static.save(program, model_path, pickle_protocol=2) +.. py:function:: paddle.static.save(program, model_path, protocol=2) :api_attr: 声明式编程模式(静态图) @@ -19,7 +19,7 @@ save 参数: - **program** ( :ref:`cn_api_fluid_Program` ) – 要保存的Program。 - **model_path** (str) – 保存program的文件前缀。格式为 ``目录名称/文件前缀``。如果文件前缀为空字符串,会引发异常。 - - **pickle_protocol** (int, 可选) – pickle模块的协议版本,默认值为2,取值范围是[2,4]。 + - **protocol** (int, 可选) – pickle模块的协议版本,默认值为2,取值范围是[2,4]。在Python3环境中,推荐使用 ``protocol=4``。 返回: 无 diff --git a/doc/paddle/api/paddle/framework/io/load_cn.rst b/doc/paddle/api/paddle/framework/io/load_cn.rst index 5f1f437db41..3210eead920 100644 --- a/doc/paddle/api/paddle/framework/io/load_cn.rst +++ b/doc/paddle/api/paddle/framework/io/load_cn.rst @@ -8,21 +8,20 @@ load 从指定路径载入可以在paddle中使用的对象实例。 .. note:: - 目前仅支持载入 Layer 或者 Optimizer 的 ``state_dict`` 。 + 目前支持载入:Layer 或者 Optimizer 的 ``state_dict``,Layer对象,Tensor以及包含Tensor的嵌套list、tuple、dict,Program。 -.. note:: - 为了更高效地使用paddle存储的模型参数, ``paddle.load`` 支持从除 ``paddle.save`` 之外的其他save相关API的存储结果中载入 ``state_dict`` ,但是在不同场景中,参数 ``path`` 的形式有所不同: - 1. 从 ``paddle.static.save`` 或者 ``paddle.Model().save(training=True)`` 的保存结果载入: ``path`` 需要是完整的文件名,例如 ``model.pdparams`` 或者 ``model.opt`` ; - 2. 从 ``paddle.jit.save`` 或者 ``paddle.static.save_inference_model`` 或者 ``paddle.Model().save(training=False)`` 的保存结果载入: ``path`` 需要是路径前缀, 例如 ``model/mnist`` , ``paddle.load`` 会从 ``mnist.pdmodel`` 和 ``mnist.pdiparams`` 中解析 ``state_dict`` 的信息并返回。 - 3. 从paddle 1.x API ``paddle.fluid.io.save_inference_model`` 或者 ``paddle.fluid.io.save_params/save_persistables`` 的保存结果载入: ``path`` 需要是目录,例如 ``model`` ,此处model是一个文件夹路径。 -.. note:: - 如果从 ``paddle.static.save`` 或者 ``paddle.static.save_inference_model`` 等静态图API的存储结果中载入 ``state_dict`` ,动态图模式下参数的结构性变量名将无法被恢复。在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。 +遇到使用问题,请参考: + + .. toctree:: + :maxdepth: 1 + + ../../../../faq/save_cn.md 参数 ::::::::: - path (str) – 载入目标对象实例的路径。通常该路径是目标文件的路径,当从用于存储预测模型API的存储结果中载入state_dict时,该路径可能是一个文件前缀或者目录。 - - **config (dict, 可选) - 其他用于兼容的载入配置选项。这些选项将来可能被移除,如果不是必须使用,不推荐使用这些配置选项。默认为 ``None``。目前支持以下配置选项:(1) model_filename (str) - paddle 1.x版本 ``save_inference_model`` 接口存储格式的预测模型文件名,原默认文件名为 ``__model__`` ; (2) params_filename (str) - paddle 1.x版本 ``save_inference_model`` 接口存储格式的参数文件名,没有默认文件名,默认将各个参数分散存储为单独的文件。 + - **config (dict, 可选) - 其他用于兼容的载入配置选项。这些选项将来可能被移除,如果不是必须使用,不推荐使用这些配置选项。默认为 ``None``。目前支持以下配置选项:(1) model_filename (str) - paddle 1.x版本 ``save_inference_model`` 接口存储格式的预测模型文件名,原默认文件名为 ``__model__`` ; (2) params_filename (str) - paddle 1.x版本 ``save_inference_model`` 接口存储格式的参数文件名,没有默认文件名,默认将各个参数分散存储为单独的文件; (3) return_numpy(bool) - 如果被指定为 ``True`` ,``load`` 的结果中的Tensor会被转化为 ``numpy.ndarray`` ,默认为 ``False`` 。 返回 ::::::::: @@ -33,10 +32,12 @@ Object,一个可以在paddle中使用的对象实例 .. code-block:: python + # example 1: dynamic graph import paddle - emb = paddle.nn.Embedding(10, 10) layer_state_dict = emb.state_dict() + + # save state_dict of emb paddle.save(layer_state_dict, "emb.pdparams") scheduler = paddle.optimizer.lr.NoamDecay( @@ -45,7 +46,77 @@ Object,一个可以在paddle中使用的对象实例 learning_rate=scheduler, parameters=emb.parameters()) opt_state_dict = adam.state_dict() + + # save state_dict of optimizer paddle.save(opt_state_dict, "adam.pdopt") + # save weight of emb + paddle.save(emb.weight, "emb.weight.pdtensor") + # load state_dict of emb load_layer_state_dict = paddle.load("emb.pdparams") + # load state_dict of optimizer load_opt_state_dict = paddle.load("adam.pdopt") + # load weight of emb + load_weight = paddle.load("emb.weight.pdtensor") + +.. code-block:: python + + # example 2: Load multiple state_dict at the same time + import paddle + from paddle import nn + from paddle.optimizer import Adam + + layer = paddle.nn.Linear(3, 4) + adam = Adam(learning_rate=0.001, parameters=layer.parameters()) + obj = {'model': layer.state_dict(), 'opt': adam.state_dict(), 'epoch': 100} + path = 'example/model.pdparams' + paddle.save(obj, path) + obj_load = paddle.load(path) + + +.. code-block:: python + + # example 3: static graph + import paddle + import paddle.static as static + + paddle.enable_static() + + # create network + x = paddle.static.data(name="x", shape=[None, 224], dtype='float32') + z = paddle.static.nn.fc(x, 10) + + place = paddle.CPUPlace() + exe = paddle.static.Executor(place) + exe.run(paddle.static.default_startup_program()) + prog = paddle.static.default_main_program() + for var in prog.list_vars(): + if list(var.shape) == [224, 10]: + tensor = var.get_value() + break + + # save/load tensor + path_tensor = 'temp/tensor.pdtensor' + paddle.save(tensor, path_tensor) + load_tensor = paddle.load(path_tensor) + + # save/load state_dict + path_state_dict = 'temp/model.pdparams' + paddle.save(prog.state_dict("param"), path_tensor) + load_state_dict = paddle.load(path_tensor) + +.. code-block:: python + + # example 4: load program + import paddle + + paddle.enable_static() + + data = paddle.static.data( + name='x_static_save', shape=(None, 224), dtype='float32') + y_static = z = paddle.static.nn.fc(data, 10) + main_program = paddle.static.default_main_program() + path = "example/main_program.pdmodel" + paddle.save(main_program, path) + load_main = paddle.load(path) + print(load_main) diff --git a/doc/paddle/api/paddle/framework/io/save_cn.rst b/doc/paddle/api/paddle/framework/io/save_cn.rst index 942ddf57aae..7b3bc35de57 100644 --- a/doc/paddle/api/paddle/framework/io/save_cn.rst +++ b/doc/paddle/api/paddle/framework/io/save_cn.rst @@ -3,12 +3,12 @@ save ----- -.. py:function:: paddle.save(obj, path, pickle_protocol=2) +.. py:function:: paddle.save(obj, path, protocol=2) 将对象实例obj保存到指定的路径中。 .. note:: - 目前仅支持存储 Layer 或者 Optimizer 的 ``state_dict`` 。 + 目前支持保存:Layer 或者 Optimizer 的 ``state_dict``,Layer对象,Tensor以及包含Tensor的嵌套list、tuple、dict,Program。 .. note:: 不同于 ``paddle.jit.save`` ,由于 ``paddle.save`` 的存储结果是单个文件,所以不需要通过添加后缀的方式区分多个存储文件,``paddle.save`` 的输入参数 ``path`` 将直接作为存储结果的文件名而非前缀。为了统一存储文件名的格式,我们推荐使用paddle标椎文件后缀: @@ -16,11 +16,20 @@ save 2. 对于 ``Optimizer.state_dict`` ,推荐使用后缀 ``.pdopt`` 。 具体示例请参考API的代码示例。 + +遇到使用问题,请参考: + + .. toctree:: + :maxdepth: 1 + + ../../../../faq/save_cn.md + 参数 ::::::::: - **obj** (Object) – 要保存的对象实例。 - **path** (str) – 保存对象实例的路径。如果存储到当前路径,输入的path字符串将会作为保存的文件名。 - - **pickle_protocol** (int, 可选) – pickle模块的协议版本,默认值为2,取值范围是[2,4]。 + - **protocol** (int, 可选) – pickle模块的协议版本,默认值为2,取值范围是[2,4]。在Python3环境中,推荐使用 ``protocol=4``。 + - **configs** (dict, 可选) – 其他配置选项,目前支持以下选项:(1)use_binary_format(bool)- 如果被保存的对象是静态图的Tensor,你可以指定这个参数。如果被指定为 ``True`` ,这个Tensor会被保存为由paddle定义的二进制格式的文件;否则这个Tensor被保存为pickle格式。默认为 ``False`` 。 返回 ::::::::: @@ -31,10 +40,12 @@ save .. code-block:: python + # example 1: dynamic graph import paddle - emb = paddle.nn.Embedding(10, 10) layer_state_dict = emb.state_dict() + + # save state_dict of emb paddle.save(layer_state_dict, "emb.pdparams") scheduler = paddle.optimizer.lr.NoamDecay( @@ -43,4 +54,67 @@ save learning_rate=scheduler, parameters=emb.parameters()) opt_state_dict = adam.state_dict() + + # save state_dict of optimizer paddle.save(opt_state_dict, "adam.pdopt") + # save weight of emb + paddle.save(emb.weight, "emb.weight.pdtensor") + + +.. code-block:: python + + # example 2: Save multiple state_dict at the same time + import paddle + from paddle import nn + from paddle.optimizer import Adam + + layer = paddle.nn.Linear(3, 4) + adam = Adam(learning_rate=0.001, parameters=layer.parameters()) + obj = {'model': layer.state_dict(), 'opt': adam.state_dict(), 'epoch': 100} + path = 'example/model.pdparams' + paddle.save(obj, path) + + +.. code-block:: python + + # example 3: static graph + import paddle + import paddle.static as static + + paddle.enable_static() + + # create network + x = paddle.static.data(name="x", shape=[None, 224], dtype='float32') + z = paddle.static.nn.fc(x, 10) + + place = paddle.CPUPlace() + exe = paddle.static.Executor(place) + exe.run(paddle.static.default_startup_program()) + prog = paddle.static.default_main_program() + for var in prog.list_vars(): + if list(var.shape) == [224, 10]: + tensor = var.get_value() + break + + # save/load tensor + path_tensor = 'temp/tensor.pdtensor' + paddle.save(tensor, path_tensor) + + # save/load state_dict + path_state_dict = 'temp/model.pdparams' + paddle.save(prog.state_dict("param"), path_tensor) + + +.. code-block:: python + + # example 4: save program + import paddle + + paddle.enable_static() + + data = paddle.static.data( + name='x_static_save', shape=(None, 224), dtype='float32') + y_static = z = paddle.static.nn.fc(data, 10) + main_program = paddle.static.default_main_program() + path = "example/main_program.pdmodel" + paddle.save(main_program, path) diff --git a/doc/paddle/faq/save_cn.md b/doc/paddle/faq/save_cn.md index 526c41eb1af..f54c7cb67f8 100644 --- a/doc/paddle/faq/save_cn.md +++ b/doc/paddle/faq/save_cn.md @@ -46,6 +46,44 @@ emb.set_state_dict(para_state_dict) adam.set_state_dict(opti_state_dict) ``` +##### 问题:paddle.load可以加载哪些API产生的结果呢? ++ 答复: + + 为了更高效地使用paddle存储的模型参数,`paddle.load`支持从除`paddle.save`之外的其他save相关API的存储结果中载入`state_dict`,但是在不同场景中,参数`path`的形式有所不同: + 1. 从`paddle.static.save`或者`paddle.Model().save(training=True)`的保存结果载入:`path`需要是完整的文件名,例如`model.pdparams`或者`model.opt`; + 2. 从`paddle.jit.save`或者`paddle.static.save_inference_model`或者`paddle.Model().save(training=False)`的保存结果载入:`path`需要是路径前缀, 例如`model/mnist`,`paddle.load`会从`mnist.pdmodel`和`mnist.pdiparams`中解析`state_dict`的信息并返回。 + 3. 从paddle 1.x API`paddle.fluid.io.save_inference_model`或者`paddle.fluid.io.save_params/save_persistables`的保存结果载入:`path`需要是目录,例如`model`,此处model是一个文件夹路径。 + + + 需要注意的是,如果从`paddle.static.save`或者`paddle.static.save_inference_model`等静态图API的存储结果中载入`state_dict`,动态图模式下参数的结构性变量名将无法被恢复。在将载入的`state_dict`配置到当前Layer中时,需要配置`Layer.set_state_dict`的参数`use_structured_name=False`。 + +##### 问题:paddle.save 是如何保存state_dict,Layer对象,Tensor以及包含Tensor的嵌套list、tuple、dict的呢? ++ 答复: + 1. 对于``state_dict``保存方式与paddle2.0完全相同,我们将``Tensor``转化为``numpy.ndarray``保存。 + + 2. 对于其他形式的包含``Tensor``的对象(``Layer``对象,单个``Tensor``以及包含``Tensor``的嵌套``list``、``tuple``、``dict``),在动态图中,将``Tensor``转化为``tuple(Tensor.name, Tensor.numpy())``;在静态图中,将``Tensor``直接转化为``numpy.ndarray``。之所以这样做,是因为当在静态图中使用动态保存的模型时,有时需要``Tensor``的名字因此将名字保存下来,同时,在``load``时区分这个``numpy.ndarray``是由Tenosr转化而来还是本来就是``numpy.ndarray``;保存静态图的``Tensor``时,通常通过``Variable.get_value``得到``Tensor``再使用``paddle.save``保存``Tensor``,此时,``Variable``是有名字的,这个``Tensor``是没有名字的,因此将静态图``Tensor``直接转化为``numpy.ndarray``保存。 + > 此处动态图Tensor和静态图Tensor是不相同的,动态图Tensor有name、stop_gradient等属性;而静态图的Tensor是比动态图Tensor轻量级的,只包含place等基本信息,不包含名字等。 + +##### 问题:将Tensor转换为numpy.ndarray或者tuple(Tensor.name, Tensor.numpy())不是惟一可译编码,为什么还要做这样的转换呢? ++ 答复: + + 1. 我们希望``paddle.save``保存的模型能够不依赖paddle框架就能够被用户解析(pickle格式模型),这样用户可以方便的做调试,轻松的看到保存的参数的数值。其他框架的模型与paddle模型做转化也会容易很多。 + + 2. 我们希望保存的模型尽量小,只保留了能够满足大多场景的信息(动态图保存名字和数值,静态图只保存数值),如果需要``Tensor``的其他信息(例如``stop_gradient``),可以向被保存的对象中添加这些信息,``load``之后再还原这些信息。这样的转换方式可以覆盖绝大多数场景,一些特殊场景也是可以通过一些方法解决的,如下面的问题。 + +##### 问题:什么情况下save与load的结果不一致呢,应该如何避免这种情况发生呢? ++ 答复: + + 以下情况会造成save与load的结果不一致: + 1. 被保存的对象包含动态图``Tensor``同时包含``tuple(string, numpy.ndarray)``; + 2. 被保存的对象包含静态图``Tensor``,同时包含``numpy.ndarray``或者``tuple(string, numpy.ndarray)``; + 3. 被保存的对象只包含``numpy.ndarray``,但是包含``tuple(string, numpy.ndarray)``。 + + 针对这些情况我们有以下建议: + 1. 被保存的对象(包括``Layer``对象中的``ParamBase``),避免包含形如``tuple(string, numpy.ndarray)``的对象; + 2. 如果被保存的对象包含``numpy.ndarray``,尽量在``load``时设置``return_numpy = True``。 + 3. 对于``Layer``对象,只保存参数的值和名字,如果需要其他信息(例如``stop_gradient``),请将手将这些信息打包成`dict`等,一并保存。 + 更多介绍请参考以下API文档: - [paddle.save](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/framework/io/save_cn.html)