|
1 | 1 | .. _user_guide_save_load_vars: |
2 | 2 |
|
3 | 3 | ################## |
4 | | -保存与载入模型变量 |
| 4 | +模型/变量的保存、载入与增量训练 |
5 | 5 | ################## |
6 | 6 |
|
7 | 7 | 模型变量分类 |
|
37 | 37 | 那么我们应该将各种长期变量都保存下来,甚至还需要记录一下当前的epoch和step的id。 |
38 | 38 | 因为一些模型变量虽然不是参数,但对于模型的训练依然必不可少。 |
39 | 39 |
|
40 | | -因此,根据需求的不同,我们提供了两套API来分别进行模型的参数和checkpoint的保存。 |
41 | | - |
42 | 40 | 保存模型用于对新样本的预测 |
43 | 41 | ========================== |
44 | 42 |
|
|
61 | 59 | 筛选出其中所有的模型参数,并将这些模型参数保存到指定的 :code:`param_path` 之中。 |
62 | 60 |
|
63 | 61 |
|
64 | | -保存checkpoint用于将来恢复训练 |
65 | | -============================== |
66 | | - |
67 | | -在训练过程中,我们可能希望在一些节点上将当前的训练状态保存下来, |
68 | | -以便在将来需要的时候恢复训练环境继续进行训练。这一般被称作“checkpoint”。 |
69 | | -想要保存checkpoint,可以使用 :code:`fluid.io.save_checkpiont()` 接口。 |
70 | | - |
71 | | -例如: |
72 | | - |
73 | | -.. code-block:: python |
74 | | -
|
75 | | - import paddle.fluid as fluid |
76 | | -
|
77 | | - exe = fluid.Executor(fluid.CPUPlace()) |
78 | | - path = "./checkpoints" |
79 | | - prog = fluid.default_main_program() |
80 | | - trainer_args = {"epoch_id": 200, |
81 | | - "step_id": 20} # just an example |
82 | | - fluid.io.save_checkpoint(executor=exe, |
83 | | - checkpoint_dir=path, |
84 | | - trainer_id=0, |
85 | | - trainer_args=trainer_args, |
86 | | - main_program=prog, |
87 | | - max_num_checkpoints=3) |
88 | | -
|
89 | | -上面的例子中,通过调用 :code:`fluid.io.save_checkpoint` 函数,PaddlePaddle Fluid会对默认 |
90 | | -:code:`fluid.Program` 也就是 :code:`prog` 中的所有模型变量进行扫描, |
91 | | -根据一系列内置的规则自动筛选出其中所有需要保存的变量,并将他们保存到指定的 :code:`path` 目录下。 |
92 | | - |
93 | | -:code:`fluid.io.save_checkpoint` 的各个参数中, :code:`trainer_id` 在单机情况下设置为0即可; :code:`trainer_args` |
94 | | -为一个Python dict,用于给定当前的epoch_id和step_id; |
95 | | -:code:`max_num_checkpoints` 用于表示的最大checkpoint数量, |
96 | | -如果目录中已经存在的checkpoint数量超过这个值,那最早的checkpoint将被删除。 |
97 | 62 |
|
98 | 63 | 如何载入模型变量 |
99 | 64 | ################ |
100 | 65 |
|
101 | | -与模型变量的保存相对应,我们提供了两套API来分别载入模型的参数和载入模型的checkpoint。 |
| 66 | +与模型变量的保存相对应,我们提供了两套API来分别载入模型的参数和载入模型的长期变量。 |
102 | 67 |
|
103 | 68 | 载入模型用于对新样本的预测 |
104 | 69 | ========================== |
|
132 | 97 | 之前。如果在之后运行,可能会覆盖已加载的模型参数导致错误。 |
133 | 98 |
|
134 | 99 |
|
135 | | -载入checkpoint用于恢复训练 |
| 100 | + |
| 101 | +预测所用的模型与参数的保存: |
| 102 | +################## |
| 103 | +预测引擎提供了存储预测模型 :code:`fluid.io.save_inference_model` 和加载预测模型 :code:`fluid.io.load_inference_model` 两个接口。 |
| 104 | + |
| 105 | +- :code:`fluid.io.save_inference_model`:请参考 :ref:`api_guide_inference`。 |
| 106 | +- :code:`fluid.io.load_inference_model`:请参考 :ref:`api_guide_inference`。 |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | +增量训练 |
| 111 | +############ |
| 112 | +增量训练指一个学习系统能不断地从新样本中学习新的知识,并能保存大部分以前已经学习到的知识。因此增量学习涉及到两点:在上一次训练结束的时候保存需要持久化的参数, 在下一次训练开始的时候加载上一次保存的持久化参数。 因此增量训练涉及到如下几个API: |
| 113 | +:code:`fluid.io.save_persistables`、:code:`fluid.io.load_persistables` 。 |
| 114 | + |
| 115 | +单机增量训练 |
136 | 116 | ========================== |
| 117 | +单机的增量训练的一般步骤如下: |
| 118 | + |
| 119 | +1. 在训练的最后调用 :code:`fluid.io.save_persistables` 保存持久性参数到指定的位置。 |
| 120 | +2. 在训练的startup_program通过执行器 :code:`Executor` 执行成功之后调用 :code:`fluid.io.load_persistables` 加载之前保存的持久性参数。 |
| 121 | +3. 通过执行器 :code:`Executor` 或者 :code:`ParallelExecutor` 继续训练。 |
137 | 122 |
|
138 | | -对于通过 :code:`fluid.io.save_checkpoint` 保存的模型,可以使用 :code:`fluid.io.load_checkpoint` |
139 | | -来进行载入。 |
140 | 123 |
|
141 | 124 | 例如: |
142 | 125 |
|
|
145 | 128 | import paddle.fluid as fluid |
146 | 129 |
|
147 | 130 | exe = fluid.Executor(fluid.CPUPlace()) |
148 | | - path = "./checkpoints" |
| 131 | + path = "./models" |
149 | 132 | prog = fluid.default_main_program() |
150 | | - fluid.io.load_checkpoint(executor=exe, checkpoint_dir=path, |
151 | | - serial=9, main_program=prog) |
152 | | -
|
153 | | -上面的例子中,通过调用 :code:`fluid.io.save_checkpoint` 函数,PaddlePaddle Fluid会对 |
154 | | -:code:`prog` 中的所有模型变量进行扫描,根据内置规则自动筛选出需要加载的变量, |
155 | | -并尝试从 :code:`path` 之中加载它们。 |
| 133 | + fluid.io.save_persistables(exe, path, prog) |
156 | 134 |
|
157 | | -参数 :code:`serial` 用来标记具体要加载的checkpoint的版本号。在保存checkpoint的时候, |
158 | | -一个checkpoint会被保存在一个子目录中,并在目录名上体现出自己的版本号。 |
159 | | -一般越大的版本号表示这个checkpoint越新。 |
| 135 | +上面的例子中,通过调用 :code:`fluid.io.save_persistables` 函数,PaddlePaddle Fluid会从默认 :code:`fluid.Program` 也就是 :code:`prog` 的所有模型变量中找出长期变量,并将他们保存到指定的 :code:`path` 目录下。 |
160 | 136 |
|
161 | | -这里的 :code:`prog` 必须和调用 :code:`fluid.io.save_checkpoint` 时所用的 :code:`prog` |
162 | | -完全一致,否则会导致变量加载错误或者未加载。另外,与 :code:`fluid.io.save_params` 类似, |
163 | | -运行 :code:`fluid.default_startup_program()` 也必须在 :code:`fluid.io.load_checkpoint` |
164 | | -之前进行。 |
165 | 137 |
|
166 | | -多机checkpoint保存 |
167 | | -################## |
168 | | - |
169 | | -Checkpoint功能使用指南 |
170 | | -====================== |
171 | | - |
172 | | -* 背景 |
173 | | -单机/多机在训练过程中会由于软件/硬件的问题出现异常,导致训练中断,进而导致训练无结果或结果不可用,浪费大量时间和机器性能。 |
| 138 | +.. code-block:: python |
174 | 139 |
|
175 | | -* 目的 |
176 | | -Checkpoint功能能够在训练中途对训练数据中间数据进行保存,出现异常恢复训练的时候能够加载中途保存的数据继续训练, 实现单机/多机的容错训练的功能。 |
| 140 | + import paddle.fluid as fluid |
177 | 141 |
|
178 | | -* 说明 |
| 142 | + exe = fluid.Executor(fluid.CPUPlace()) |
| 143 | + path = "./models" |
| 144 | + startup_prog = fluid.default_startup_program() |
| 145 | + exe.run(startup_prog) |
| 146 | + fluid.io.load_persistables(exe, path, startup_prog) |
| 147 | + main_prog = fluid.default_main_program() |
| 148 | + exe.run(main_prog) |
| 149 | + |
| 150 | +上面的例子中,通过调用 :code:`fluid.io.load_persistables` 函数,PaddlePaddle Fluid会从默认 |
| 151 | +:code:`fluid.Program` 也就是 :code:`prog` 的所有模型变量中找出长期变量,从指定的 :code:`path` 目录中将它们一一加载, 然后再继续进行训练。 |
179 | 152 |
|
180 | | - * 目前已实现的参数保存: |
181 | 153 |
|
182 | | - 1. 基于Trainer 0 实现训练过程中的参数保存 |
183 | 154 |
|
184 | | - 2. 基于PServer 实现了`Distribute Lookup Table`相关参数保存 |
| 155 | +多机增量(不带分布式大规模稀疏矩阵)训练的一般步骤为: |
| 156 | +========================== |
| 157 | +多机增量训练和单机增量训练有若干不同点: |
185 | 158 |
|
186 | | - * Fluid Checkpoint 保存数据目录结构: |
| 159 | +1. 在训练的最后调用 :code:`fluid.io.save_persistables` 保存持久性参数时,不必要所有的trainer都调用这个方法,一般0号trainer来保存。 |
| 160 | +2. 多机增量训练的参数加载在PServer端,trainer端不用加载参数。在PServer全部启动后,trainer会从PServer端同步参数。 |
187 | 161 |
|
188 | | -.. code-block:: python |
| 162 | +多机增量(不启用分布式大规模稀疏矩阵)训练的一般步骤为: |
189 | 163 |
|
190 | | - checkpoint_dir (用户定义的checkpoint目录) |
191 | | - ├── checkpoint_0 (第一次保存) |
192 | | - │ ├── __lockup_table__ (Distribute Lookup Table 目录) |
193 | | - │ │ ├── table_pserver_0 (Pserver 0 号保存的lookup table 数据) |
194 | | - │ │ └── table_pserver_1 |
195 | | - │ ├── __model__ (model 目录) |
196 | | - │ │ └── var.w_1 |
197 | | - │ └── trainer_0 (trainer 自有数据保存) |
198 | | - │ ├── epoch_id |
199 | | - │ └── step_id |
200 | | - └── checkpoint_1 (第二次保存) |
| 164 | +1. 0号trainer在训练的最后调用 :code:`fluid.io.save_persistables` 保存持久性参数到指定的 :code:`path` 下。 |
| 165 | +2. 通过HDFS等方式将0号trainer保存下来的所有的参数共享给所有的PServer(每个PServer都需要有完整的参数)。 |
| 166 | +3. PServer在训练的startup_program通过执行器(:code:`Executor`)执行成功之后调用 :code:`fluid.io.load_persistables` 加载0号trainer保存的持久性参数。 |
| 167 | +4. PServer通过执行器 :code:`Executor` 继续启动PServer_program. |
| 168 | +5. 所有的训练节点trainer通过执行器 :code:`Executor` 或者 :code:`ParallelExecutor` 正常训练。 |
201 | 169 |
|
202 | | -* 使用方法 |
203 | 170 |
|
204 | | - * 声明Fluid.CheckpointConfig |
| 171 | +对于训练过程中待保存参数的trainer, 例如: |
205 | 172 |
|
206 | | - 用户对checkpoint功能的配置,主要是配置对象 :code:`Fluid` 中的 :code:`CheckpointConfig` . |
| 173 | +.. code-block:: python |
207 | 174 |
|
208 | | - :code:`CheckpointConfig` 包括4个参数: |
| 175 | + import paddle.fluid as fluid |
209 | 176 |
|
210 | | - ===================== ===== ========================== |
211 | | - 参数 类型 说明 |
212 | | - ===================== ===== ========================== |
213 | | - checkpoint_dir int checkpoint存储目录 |
| 177 | + exe = fluid.Executor(fluid.CPUPlace()) |
| 178 | + path = "./models" |
| 179 | + trainer_id = 0 |
| 180 | + if trainer_id == 0: |
| 181 | + prog = fluid.default_main_program() |
| 182 | + fluid.io.save_persistables(exe, path, prog) |
214 | 183 |
|
215 | | - max_num_checkpoints int 最大保存的checkpoint副本数 |
216 | 184 |
|
217 | | - epoch_interval int 每隔epoch_interval轮epoch |
| 185 | +.. code-block:: bash |
| 186 | + hadoop fs -mkdir /remote/$path |
| 187 | + hadoop fs -put $path /remote/$path |
218 | 188 |
|
219 | | - step_interval int 每隔step_interval轮step |
220 | | - ===================== ===== ========================== |
| 189 | +上面的例子中,0号train通过调用 :code:`fluid.io.save_persistables` 函数,PaddlePaddle Fluid会从默认 |
| 190 | +:code:`fluid.Program` 也就是 :code:`prog` 的所有模型变量中找出长期变量,并将他们保存到指定的 :code:`path` 目录下。然后通过调用第三方的文件系统(如HDFS)将存储的模型进行上传到所有PServer都可访问的位置。 |
221 | 191 |
|
222 | | - * 在Fluid.Trainer对象的声明中加入Fluid.CheckpointConfig的声明 |
| 192 | +对于训练过程中待载入参数的PServer, 例如: |
223 | 193 |
|
224 | | - Trainer的__init__方法的参数中包含了对 :code:`CheckpointConfig` , 需要传入在声明Trainer前声明的 :code:`CheckpointConfig` 对象。 |
225 | | - 如: |
226 | 194 |
|
227 | | - .. code-block:: python |
| 195 | +.. code-block:: bash |
| 196 | + hadoop fs -get /remote/$path $path |
228 | 197 |
|
229 | | - config = CheckpointConfig( |
230 | | - checkpoint_dir = "/tmp/ckpt", max_num_checkpoints = 2, |
231 | | - epoch_interval = 2, step_interval = 10) |
232 | | - trainer = Trainer(..., checkpoint_config=config) |
233 | 198 |
|
234 | | -定义和声明完成后, 训练在运行过程中就会在指定的step和epoch处进行保存,出现异常时,就会自动从最新的checkpoint目录进行参数恢复啦! |
| 199 | +.. code-block:: python |
235 | 200 |
|
236 | | -* 相关API |
| 201 | + import paddle.fluid as fluid |
237 | 202 |
|
238 | | - `Trainer API 说明 <https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/trainer.py>`_ |
| 203 | + exe = fluid.Executor(fluid.CPUPlace()) |
| 204 | + path = "./models" |
| 205 | + pserver_endpoints = "127.0.0.1:1001,127.0.0.1:1002" |
| 206 | + trainers = 4 |
| 207 | + training_role == "PSERVER" |
| 208 | + config = fluid.DistributeTranspilerConfig() |
| 209 | + t = fluid.DistributeTranspiler(config=config) |
| 210 | + t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers, sync_mode=True) |
| 211 | +
|
| 212 | + if training_role == "PSERVER": |
| 213 | + current_endpoint = "127.0.0.1:1001" |
| 214 | + pserver_prog = t.get_pserver_program(current_endpoint) |
| 215 | + pserver_startup = t.get_startup_program(current_endpoint, pserver_prog) |
| 216 | +
|
| 217 | + exe.run(pserver_startup) |
| 218 | + fluid.io.load_persistables(exe, path, pserver_startup) |
| 219 | + exe.run(pserver_prog) |
| 220 | + if training_role == "TRAINER": |
| 221 | + main_program = t.get_trainer_program() |
| 222 | + exe.run(main_program) |
| 223 | +
|
| 224 | +上面的例子中,每个PServer通过调用HDFS的命令获取到0号trainer保存的参数,通过配置获取到PServer的 :code:`fluid.Program` ,PaddlePaddle Fluid会从此 |
| 225 | +:code:`fluid.Program` 也就是 :code:`pserver_startup` 的所有模型变量中找出长期变量,并通过指定的 :code:`path` 目录下一一加载。 |
239 | 226 |
|
240 | | -* 注意 |
241 | 227 |
|
242 | | -1. 保证每个训练的 :code:`checkpoint_dir` 与其他训练独立。 |
243 | | -2. 最大副本数量 :code:`max_num_checkpoints` 需要根据磁盘容量以及模型的大小进行调整, 保证磁盘的可用性。 |
244 | | -3. :code:`epoch_interval` 和 :code:`step_interval` 不宜过小, 频繁的进行checkpoint会拖慢训练速度。 |
245 | | -4. **分布式训练** 的过程中:每个Trainer都会在 :code:`checkpoint_dir` 目录中保存当前Trainer的参数(只有Trainer 0会保存模型的参数),需要 **分布式文件系统(HDFS等)** 将同 :code:`checkpoint_dir` 目录的数据进行合并才能得到完整的数据,恢复训练的时候需要用完整的数据进行恢复。 |
0 commit comments