模型/变量的保存、载入与增量训练

    1. 模型参数
    1. 长期变量
    1. 临时变量

    如何保存模型变量

    根据用途的不同,我们需要保存的模型变量也是不同的。例如,如果我们只是想保存模型用来进行以后的预测, 那么只保存模型参数就够用了。但如果我们需要保存一个checkpoint(检查点,类似于存档,存有复现目前模型的必要信息)以备将来恢复训练, 那么我们应该将各种长期变量都保存下来,甚至还需要记录一下当前的epoch和step的id。 因为一些模型变量虽然不是参数,但对于模型的训练依然必不可少。

    1. save_inference_model 会根据用户配置的 feeded_var_namestarget_vars 进行网络裁剪,保存下裁剪后的网络结构的 __model__ 以及裁剪后网络中的长期变量
    2. save_persistables 不会保存网络结构,会保存网络中的全部长期变量到指定位置。
    3. save_vars 不会保存网络结构,会根据用户指定的 fluid.framework.Parameter 列表进行保存。

    如果我们保存模型的目的是用于对新样本的预测,那么只保存模型参数就足够了。我们可以使用 fluid.io.save_params() 接口来进行模型参数的保存。

    例如:

    上面的例子中,通过调用 fluid.io.save_params 函数,PaddlePaddle Fluid会对默认 fluid.Program 也就是 prog 中的所有模型变量进行扫描, 筛选出其中所有的模型参数,并将这些模型参数保存到指定的 param_path 之中。

    如何载入模型变量

    对于通过 fluid.io.save_params 保存的模型,可以使用 fluid.io.load_params 来进行载入。

    例如:

    1. import paddle.fluid as fluid
    2. exe = fluid.Executor(fluid.CPUPlace())
    3. param_path = "./my_paddle_model"
    4. prog = fluid.default_main_program()
    5. fluid.io.load_params(executor=exe, dirname=param_path,
    6. main_program=prog)

    上面的例子中,通过调用 fluid.io.load_params 函数,PaddlePaddle Fluid会对 prog 中的所有模型变量进行扫描,筛选出其中所有的模型参数, 并尝试从 param_path 之中读取加载它们。

    需要格外注意的是,这里的 prog 必须和调用 fluid.io.save_params 时所用的 prog 中的前向部分完全一致,且不能包含任何参数更新的操作。如果两者存在不一致, 那么可能会导致一些变量未被正确加载;如果错误地包含了参数更新操作,那可能会导致正常预测过程中参数被更改。 这两个 fluid.Program 之间的关系类似于训练 fluid.Program 和测试 fluid.Program 之间的关系,详见: 训练过程中评测模型

    另外,需特别注意运行 fluid.default_startup_program() 必须在调用 fluid.io.load_params 之前。如果在之后运行,可能会覆盖已加载的模型参数导致错误。

    用户可以灵活地使用numpy数组设置模型参数的值,具体示例如下:

    预测引擎提供了存储预测模型 fluid.io.save_inference_model 和加载预测模型 fluid.io.load_inference_model 两个接口。

    • fluid.io.save_inference_model:请参考 。
    • fluid.io.load_inference_model:请参考 预测引擎

    增量训练

    增量训练指一个学习系统能不断地从新样本中学习新的知识,并能保存大部分以前已经学习到的知识。因此增量学习涉及到两点:在上一次训练结束的时候保存需要的长期变量, 在下一次训练开始的时候加载上一次保存的这些长期变量。 因此增量训练涉及到如下几个API: fluid.io.save_persistablesfluid.io.load_persistables

    1. 在训练的最后调用 fluid.io.save_persistables 保存持久性参数到指定的位置。
    2. 在训练的startup_program通过执行器 Executor 执行成功之后调用 fluid.io.load_persistables 加载之前保存的持久性参数。
    3. 通过执行器 Executor 或者 ParallelExecutor 继续训练。

    例如:

    1. import paddle.fluid as fluid
    2. exe = fluid.Executor(fluid.CPUPlace())
    3. prog = fluid.default_main_program()

    上面的例子中,通过调用 fluid.io.save_persistables 函数,PaddlePaddle Fluid会从默认 fluid.Program 也就是 prog 的所有模型变量中找出长期变量,并将他们保存到指定的 path 目录下。

    上面的例子中,通过调用 fluid.io.load_persistables 函数,PaddlePaddle Fluid会从默认 fluid.Program 也就是 prog 的所有模型变量中找出长期变量,从指定的 path 目录中将它们一一加载, 然后再继续进行训练。

    多机增量训练和单机增量训练有若干不同点:

    1. 在训练的最后调用 fluid.io.save_persistables 保存长期变量时,不必要所有的trainer都调用这个方法来保存,一般0号trainer来保存即可。
    2. 多机增量训练的参数加载在PServer端,trainer端不用加载参数。在PServer全部启动后,trainer会从PServer端同步参数。
    3. 在确认需要使用增量的情况下, 多机在调用 fluid.DistributeTranspiler.transpile 时需要指定 current_endpoint 参数。

    多机增量(不带分布式大规模稀疏矩阵)训练的一般步骤为:

    1. 0号trainer在训练的最后调用 fluid.io.save_persistables 保存持久性参数到指定的 path 下。
    2. 通过HDFS等方式将0号trainer保存下来的所有的参数共享给所有的PServer(每个PServer都需要有完整的参数)。
    3. PServer在训练的startup_program通过执行器(Executor)执行成功之后调用 fluid.io.load_persistables 加载0号trainer保存的持久性参数。
    4. PServer通过执行器 Executor 继续启动PServer_program.
    5. 所有的训练节点trainer通过执行器 Executor 或者 ParallelExecutor 正常训练。

    对于训练过程中待保存参数的trainer, 例如:

    1. import paddle.fluid as fluid
    2. exe = fluid.Executor(fluid.CPUPlace())
    3. path = "./models"
    4. trainer_id = 0
    5. if trainer_id == 0:
    6. fluid.io.save_persistables(exe, path, prog)

    上面的例子中,0号trainer通过调用 fluid.io.save_persistables 函数,PaddlePaddle Fluid会从默认 fluid.Program 也就是 prog 的所有模型变量中找出长期变量,并将他们保存到指定的 path 目录下。然后通过调用第三方的文件系统(如HDFS)将存储的模型进行上传到所有PServer都可访问的位置。

    对于训练过程中待载入参数的PServer, 例如: