模型/变量的保存、载入与增量训练
- 模型参数
- 长期变量
- 临时变量
如何保存模型变量
根据用途的不同,我们需要保存的模型变量也是不同的。例如,如果我们只是想保存模型用来进行以后的预测, 那么只保存模型参数就够用了。但如果我们需要保存一个checkpoint(检查点,类似于存档,存有复现目前模型的必要信息)以备将来恢复训练, 那么我们应该将各种长期变量都保存下来,甚至还需要记录一下当前的epoch和step的id。 因为一些模型变量虽然不是参数,但对于模型的训练依然必不可少。
save_inference_model
会根据用户配置的feeded_var_names
和target_vars
进行网络裁剪,保存下裁剪后的网络结构的__model__
以及裁剪后网络中的长期变量save_persistables
不会保存网络结构,会保存网络中的全部长期变量到指定位置。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
来进行载入。
例如:
import paddle.fluid as fluid
exe = fluid.Executor(fluid.CPUPlace())
param_path = "./my_paddle_model"
prog = fluid.default_main_program()
fluid.io.load_params(executor=exe, dirname=param_path,
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_persistables
、fluid.io.load_persistables
。
- 在训练的最后调用
fluid.io.save_persistables
保存持久性参数到指定的位置。 - 在训练的startup_program通过执行器
Executor
执行成功之后调用fluid.io.load_persistables
加载之前保存的持久性参数。 - 通过执行器
Executor
或者ParallelExecutor
继续训练。
例如:
import paddle.fluid as fluid
exe = fluid.Executor(fluid.CPUPlace())
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
目录中将它们一一加载, 然后再继续进行训练。
多机增量训练和单机增量训练有若干不同点:
- 在训练的最后调用
fluid.io.save_persistables
保存长期变量时,不必要所有的trainer都调用这个方法来保存,一般0号trainer来保存即可。 - 多机增量训练的参数加载在PServer端,trainer端不用加载参数。在PServer全部启动后,trainer会从PServer端同步参数。
- 在确认需要使用增量的情况下, 多机在调用
fluid.DistributeTranspiler.transpile
时需要指定current_endpoint
参数。
多机增量(不带分布式大规模稀疏矩阵)训练的一般步骤为:
- 0号trainer在训练的最后调用
fluid.io.save_persistables
保存持久性参数到指定的path
下。 - 通过HDFS等方式将0号trainer保存下来的所有的参数共享给所有的PServer(每个PServer都需要有完整的参数)。
- PServer在训练的startup_program通过执行器(
Executor
)执行成功之后调用fluid.io.load_persistables
加载0号trainer保存的持久性参数。 - PServer通过执行器
Executor
继续启动PServer_program. - 所有的训练节点trainer通过执行器
Executor
或者ParallelExecutor
正常训练。
对于训练过程中待保存参数的trainer, 例如:
import paddle.fluid as fluid
exe = fluid.Executor(fluid.CPUPlace())
path = "./models"
trainer_id = 0
if trainer_id == 0:
fluid.io.save_persistables(exe, path, prog)
上面的例子中,0号trainer通过调用 fluid.io.save_persistables
函数,PaddlePaddle Fluid会从默认 fluid.Program
也就是 prog
的所有模型变量中找出长期变量,并将他们保存到指定的 path
目录下。然后通过调用第三方的文件系统(如HDFS)将存储的模型进行上传到所有PServer都可访问的位置。
对于训练过程中待载入参数的PServer, 例如: