save_load_variables.rst 11.2 KB
Newer Older
Y
yuyang18 已提交
1 2 3 4 5 6 7 8 9
.. _user_guide_save_load_vars:

##################
保存与载入模型变量
##################

模型变量分类
############

T
Tink_Y 已提交
10
在PaddlePaddle Fluid中,所有的模型变量都用 :code:`fluid.Variable()` 作为基类进行表示。
F
fengjiayi 已提交
11 12 13 14 15 16
在该基类之下,模型变量主要可以分为以下几种类别:

1. 模型参数
  模型参数是深度学习模型中被训练和学习的变量,在训练过程中,训练框架根据反向传播算法计算出每一个模型参数当前的梯度,
  并用优化器根据梯度对参数进行更新。模型的训练过程本质上可以看做是模型参数不断迭代更新的过程。
  在PaddlePaddle Fluid中,模型参数用 :code:`fluid.framework.Parameter` 来表示,
T
Tink_Y 已提交
17
  这是一个 :code:`fluid.Variable()` 的派生类,除了 :code:`fluid.Variable()` 具有的各项性质以外,
F
fengjiayi 已提交
18 19 20 21
  :code:`fluid.framework.Parameter` 还可以配置自身的初始化方法、更新率等属性。

2. 长期变量
  长期变量指的是在整个训练过程中持续存在、不会因为一个迭代的结束而被销毁的变量,例如动态调节的全局学习率等。
T
Tink_Y 已提交
22
  在PaddlePaddle Fluid中,长期变量通过将 :code:`fluid.Variable()` 的 :code:`persistable`
F
fengjiayi 已提交
23 24 25 26 27 28 29 30
  属性设置为 :code:`True` 来表示。所有的模型参数都是长期变量,但并非所有的长期变量都是模型参数。

3. 临时变量
  不属于上面两个类别的所有模型变量都是临时变量,这种类型的变量只在一个训练迭代中存在,在每一个迭代结束后,
  所有的临时变量都会被销毁,然后在下一个迭代开始之前,又会先构造出新的临时变量供本轮迭代使用。
  一般情况下模型中的大部分变量都属于这一类别,例如输入的训练数据、一个普通的layer的输出等等。


Y
yuyang18 已提交
31 32 33 34

如何保存模型变量
################

F
fengjiayi 已提交
35 36 37 38 39 40 41 42
根据用途的不同,我们需要保存的模型变量也是不同的。例如,如果我们只是想保存模型用来进行以后的预测,
那么只保存模型参数就够用了。但如果我们需要保存一个checkpoint以备将来恢复训练,
那么我们应该将各种长期变量都保存下来,甚至还需要记录一下当前的epoch和step的id。
因为一些模型变量虽然不是参数,但对于模型的训练依然必不可少。

因此,根据需求的不同,我们提供了两套API来分别进行模型的参数和checkpoint的保存。

保存模型用于对新样本的预测
Y
yuyang18 已提交
43
==========================
F
fengjiayi 已提交
44

Y
yuyang18 已提交
45
如果我们保存模型的目的是用于对新样本的预测,那么只保存模型参数就足够了。我们可以使用
T
Tink_Y 已提交
46
:code:`fluid.io.save_params()` 接口来进行模型参数的保存。
F
fengjiayi 已提交
47 48 49 50 51 52 53 54 55 56 57 58

例如:

.. code-block:: python

    import paddle.fluid as fluid

    exe = fluid.Executor(fluid.CPUPlace())
    param_path = "./my_paddle_model"
    prog = fluid.default_main_program()
    fluid.io.save_params(executor=exe, dirname=param_path, main_program=None)

Y
yuyang18 已提交
59
上面的例子中,通过调用 :code:`fluid.io.save_params` 函数,PaddlePaddle Fluid会对默认
T
Tink_Y 已提交
60
:code:`fluid.Program` 也就是 :code:`prog` 中的所有模型变量进行扫描,
F
fengjiayi 已提交
61 62 63 64
筛选出其中所有的模型参数,并将这些模型参数保存到指定的 :code:`param_path` 之中。


保存checkpoint用于将来恢复训练
Y
yuyang18 已提交
65
==============================
F
fengjiayi 已提交
66 67 68

在训练过程中,我们可能希望在一些节点上将当前的训练状态保存下来,
以便在将来需要的时候恢复训练环境继续进行训练。这一般被称作“checkpoint”。
T
Tink_Y 已提交
69
想要保存checkpoint,可以使用 :code:`fluid.io.save_checkpiont()` 接口。
F
fengjiayi 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

例如:

.. code-block:: python

    import paddle.fluid as fluid

    exe = fluid.Executor(fluid.CPUPlace())
    path = "./checkpoints"
    prog = fluid.default_main_program()
    trainer_args = {"epoch_id": 200,
                    "step_id": 20} # just an example
    fluid.io.save_checkpoint(executor=exe,
                                checkpoint_dir=path,
                                trainer_id=0,
                                trainer_args=trainer_args,
                                main_program=prog,
                                max_num_checkpoints=3)
Y
yuyang18 已提交
88

Y
yuyang18 已提交
89
上面的例子中,通过调用 :code:`fluid.io.save_checkpoint` 函数,PaddlePaddle Fluid会对默认
T
Tink_Y 已提交
90
:code:`fluid.Program` 也就是 :code:`prog` 中的所有模型变量进行扫描,
F
fengjiayi 已提交
91 92
根据一系列内置的规则自动筛选出其中所有需要保存的变量,并将他们保存到指定的 :code:`path` 目录下。

Y
yuyang18 已提交
93
:code:`fluid.io.save_checkpoint` 的各个参数中, :code:`trainer_id` 在单机情况下设置为0即可; :code:`trainer_args`
F
fengjiayi 已提交
94 95 96
为一个Python dict,用于给定当前的epoch_id和step_id;
:code:`max_num_checkpoints` 用于表示的最大checkpoint数量,
如果目录中已经存在的checkpoint数量超过这个值,那最早的checkpoint将被删除。
Y
yuyang18 已提交
97 98 99 100

如何载入模型变量
################

Y
yuyang18 已提交
101
与模型变量的保存相对应,我们提供了两套API来分别载入模型的参数和载入模型的checkpoint。
F
fengjiayi 已提交
102 103

载入模型用于对新样本的预测
Y
yuyang18 已提交
104
==========================
F
fengjiayi 已提交
105

Y
yuyang18 已提交
106
对于通过 :code:`fluid.io.save_params` 保存的模型,可以使用 :code:`fluid.io.load_params`
F
fengjiayi 已提交
107 108 109 110 111 112
来进行载入。

例如:

.. code-block:: python

Y
yuyang18 已提交
113
    import paddle.fluid as fluid
F
fengjiayi 已提交
114 115 116 117 118 119 120

    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)

Y
yuyang18 已提交
121
上面的例子中,通过调用 :code:`fluid.io.load_params` 函数,PaddlePaddle Fluid会对
F
fengjiayi 已提交
122 123 124
:code:`prog` 中的所有模型变量进行扫描,筛选出其中所有的模型参数,
并尝试从 :code:`param_path` 之中读取加载它们。

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

Y
yuyang18 已提交
131
另外,需特别注意运行 :code:`fluid.default_startup_program()` 必须在调用 :code:`fluid.io.load_params`
F
fengjiayi 已提交
132 133 134 135
之前。如果在之后运行,可能会覆盖已加载的模型参数导致错误。


载入checkpoint用于恢复训练
Y
yuyang18 已提交
136
==========================
F
fengjiayi 已提交
137

Y
yuyang18 已提交
138
对于通过 :code:`fluid.io.save_checkpoint` 保存的模型,可以使用 :code:`fluid.io.load_checkpoint`
F
fengjiayi 已提交
139 140 141 142 143 144
来进行载入。

例如:

.. code-block:: python

Y
yuyang18 已提交
145
    import paddle.fluid as fluid
F
fengjiayi 已提交
146 147 148 149 150 151 152

    exe = fluid.Executor(fluid.CPUPlace())
    path = "./checkpoints"
    prog = fluid.default_main_program()
    fluid.io.load_checkpoint(executor=exe, checkpoint_dir=path,
                             serial=9, main_program=prog)

Y
yuyang18 已提交
153
上面的例子中,通过调用 :code:`fluid.io.save_checkpoint` 函数,PaddlePaddle Fluid会对
F
fengjiayi 已提交
154
:code:`prog` 中的所有模型变量进行扫描,根据内置规则自动筛选出需要加载的变量,
Y
yuyang18 已提交
155
并尝试从 :code:`path` 之中加载它们。
F
fengjiayi 已提交
156 157 158 159 160

参数 :code:`serial` 用来标记具体要加载的checkpoint的版本号。在保存checkpoint的时候,
一个checkpoint会被保存在一个子目录中,并在目录名上体现出自己的版本号。
一般越大的版本号表示这个checkpoint越新。

Y
yuyang18 已提交
161
这里的 :code:`prog` 必须和调用 :code:`fluid.io.save_checkpoint` 时所用的 :code:`prog`
F
fengjiayi 已提交
162
完全一致,否则会导致变量加载错误或者未加载。另外,与 :code:`fluid.io.save_params` 类似,
Y
yuyang18 已提交
163
运行 :code:`fluid.default_startup_program()` 也必须在 :code:`fluid.io.load_checkpoint`
F
fengjiayi 已提交
164
之前进行。
Y
yuyang18 已提交
165 166 167 168

多机checkpoint保存
##################

S
shanyi15 已提交
169 170
Checkpoint功能使用指南
======================
Y
yuyang18 已提交
171

S
shanyi15 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
* 背景
单机/多机在训练过程中会由于软件/硬件的问题出现异常,导致训练中断,进而导致训练无结果或结果不可用,浪费大量时间和机器性能。

* 目的
Checkpoint功能能够在训练中途对训练数据中间数据进行保存,出现异常恢复训练的时候能够加载中途保存的数据继续训练, 实现单机/多机的容错训练的功能。

* 说明

  * 目前已实现的参数保存:

  1. 基于Trainer 0 实现训练过程中的参数保存

  2. 基于PServer 实现了`Distribute Lookup Table`相关参数保存

  * Fluid Checkpoint 保存数据目录结构:

.. code-block:: python

    checkpoint_dir (用户定义的checkpoint目录)
    ├── checkpoint_0 (第一次保存)
    │   ├── __lockup_table__ (Distribute Lookup Table 目录)
    │   │   ├── table_pserver_0 (Pserver 0 号保存的lookup table 数据)
    │   │   └── table_pserver_1
    │   ├── __model__ (model 目录)
    │   │   └── var.w_1
    │   └── trainer_0 (trainer 自有数据保存)
    │       ├── epoch_id
    │       └── step_id
    └── checkpoint_1 (第二次保存)

* 使用方法

  * 声明Fluid.CheckpointConfig

  用户对checkpoint功能的配置,主要是配置对象 :code:`Fluid` 中的 :code:`CheckpointConfig` .

  :code:`CheckpointConfig` 包括4个参数:

  =====================   =====  ==========================
          参数             类型            说明
  =====================   =====  ==========================
    checkpoint_dir         int    checkpoint存储目录

    max_num_checkpoints    int    最大保存的checkpoint副本数

    epoch_interval         int    每隔epoch_interval轮epoch

    step_interval          int      每隔step_interval轮step
  =====================   =====  ==========================

  * 在Fluid.Trainer对象的声明中加入Fluid.CheckpointConfig的声明

  Trainer的__init__方法的参数中包含了对 :code:`CheckpointConfig` , 需要传入在声明Trainer前声明的 :code:`CheckpointConfig` 对象。
  如:

  .. code-block:: python

      config = CheckpointConfig(
          checkpoint_dir = "/tmp/ckpt", max_num_checkpoints = 2,
          epoch_interval = 2, step_interval = 10)
      trainer = Trainer(..., checkpoint_config=config)

定义和声明完成后, 训练在运行过程中就会在指定的step和epoch处进行保存,出现异常时,就会自动从最新的checkpoint目录进行参数恢复啦!

* 相关API

  `Trainer API 说明 <https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/trainer.py>`_

* 注意

1. 保证每个训练的 :code:`checkpoint_dir` 与其他训练独立。
2. 最大副本数量 :code:`max_num_checkpoints` 需要根据磁盘容量以及模型的大小进行调整, 保证磁盘的可用性。
3.  :code:`epoch_interval`  和  :code:`step_interval`  不宜过小, 频繁的进行checkpoint会拖慢训练速度。
4.  **分布式训练** 的过程中:每个Trainer都会在 :code:`checkpoint_dir` 目录中保存当前Trainer的参数(只有Trainer 0会保存模型的参数),需要 **分布式文件系统(HDFS等)** 将同 :code:`checkpoint_dir` 目录的数据进行合并才能得到完整的数据,恢复训练的时候需要用完整的数据进行恢复。