7_customize_runtime.md 12.5 KB
Newer Older
unknown's avatar
unknown committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# 教程 7:如何自定义模型运行参数

在本教程中,我们将介绍如何在运行自定义模型时,进行自定义参数优化方法,学习率调整策略,工作流和钩子的方法。

<!-- TOC -->

- [定制优化方法](#%E5%AE%9A%E5%88%B6%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95)
  - [使用 PyTorch 内置的优化器](#%E4%BD%BF%E7%94%A8-PyTorch-%E5%86%85%E7%BD%AE%E7%9A%84%E4%BC%98%E5%8C%96%E5%99%A8)
  - [定制用户自定义的优化器](#%E5%AE%9A%E5%88%B6%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E4%BC%98%E5%8C%96%E5%99%A8)
    - [1. 定义一个新的优化器](#1-%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%96%B0%E7%9A%84%E4%BC%98%E5%8C%96%E5%99%A8)
    - [2. 注册优化器](#2-%E6%B3%A8%E5%86%8C%E4%BC%98%E5%8C%96%E5%99%A8)
    - [3. 在配置文件中指定优化器](#3-%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%E4%BC%98%E5%8C%96%E5%99%A8)
  - [定制优化器构造器](#%E5%AE%9A%E5%88%B6%E4%BC%98%E5%8C%96%E5%99%A8%E6%9E%84%E9%80%A0%E5%99%A8)
  - [额外设定](#%E9%A2%9D%E5%A4%96%E8%AE%BE%E5%AE%9A)
- [定制学习率调整策略](#%E5%AE%9A%E5%88%B6%E5%AD%A6%E4%B9%A0%E7%8E%87%E8%B0%83%E6%95%B4%E7%AD%96%E7%95%A5)
- [定制工作流](#%E5%AE%9A%E5%88%B6%E5%B7%A5%E4%BD%9C%E6%B5%81)
- [定制钩子](#%E5%AE%9A%E5%88%B6%E9%92%A9%E5%AD%90)
  - [定制用户自定义钩子](#%E5%AE%9A%E5%88%B6%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E9%92%A9%E5%AD%90)
    - [1. 创建一个新钩子](#1-%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%96%B0%E9%92%A9%E5%AD%90)
    - [2. 注册新钩子](#2-%E6%B3%A8%E5%86%8C%E6%96%B0%E9%92%A9%E5%AD%90)
    - [3. 修改配置](#3-%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE)
  - [使用 MMCV 内置钩子](#%E4%BD%BF%E7%94%A8-MMCV-%E5%86%85%E7%BD%AE%E9%92%A9%E5%AD%90)
  - [修改默认运行的钩子](#%E4%BF%AE%E6%94%B9%E9%BB%98%E8%AE%A4%E8%BF%90%E8%A1%8C%E7%9A%84%E9%92%A9%E5%AD%90)
    - [模型权重文件配置](#%E6%A8%A1%E5%9E%8B%E6%9D%83%E9%87%8D%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE)
    - [日志配置](#%E6%97%A5%E5%BF%97%E9%85%8D%E7%BD%AE)
    - [验证配置](#%E9%AA%8C%E8%AF%81%E9%85%8D%E7%BD%AE)

<!-- TOC -->

## 定制优化方法

### 使用 PyTorch 内置的优化器

MMAction2 支持 PyTorch 实现的所有优化器,仅需在配置文件中,指定 “optimizer” 字段
例如,如果要使用 “Adam”,则修改如下。

```python
optimizer = dict(type='Adam', lr=0.0003, weight_decay=0.0001)
```

要修改模型的学习率,用户只需要在优化程序的配置中修改 “lr” 即可。
用户可根据 [PyTorch API 文档](https://pytorch.org/docs/stable/optim.html?highlight=optim#module-torch.optim) 进行参数设置

例如,如果想使用 `Adam` 并设置参数为 `torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)`
则需要进行如下修改

```python
optimizer = dict(type='Adam', lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
```

### 定制用户自定义的优化器

#### 1. 定义一个新的优化器

一个自定义的优化器可根据如下规则进行定制

假设用户想添加一个名为 `MyOptimzer` 的优化器,其拥有参数 `a`, `b``c`
可以创建一个名为 `mmaction/core/optimizer` 的文件夹,并在目录下的文件进行构建,如 `mmaction/core/optimizer/my_optimizer.py`

```python
from mmcv.runner import OPTIMIZERS
from torch.optim import Optimizer


@OPTIMIZERS.register_module()
class MyOptimizer(Optimizer):

    def __init__(self, a, b, c):

```

#### 2. 注册优化器

要找到上面定义的上述模块,首先应将此模块导入到主命名空间中。有两种方法可以实现它。

- 修改 `mmaction/core/optimizer/__init__.py` 来进行调用

  新定义的模块应导入到 `mmaction/core/optimizer/__init__.py` 中,以便注册器能找到新模块并将其添加:

```python
from .my_optimizer import MyOptimizer
```

- 在配置中使用 `custom_imports` 手动导入

```python
custom_imports = dict(imports=['mmaction.core.optimizer.my_optimizer'], allow_failed_imports=False)
```

`mmaction.core.optimizer.my_optimizer` 模块将会在程序开始阶段被导入,`MyOptimizer` 类会随之自动被注册。
注意,只有包含 `MyOptmizer` 类的包会被导入。`mmaction.core.optimizer.my_optimizer.MyOptimizer` **不会** 被直接导入。

#### 3. 在配置文件中指定优化器

之后,用户便可在配置文件的 `optimizer` 域中使用 `MyOptimizer`
在配置中,优化器由 “optimizer” 字段定义,如下所示:

```python
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
```

要使用自定义的优化器,可以将该字段更改为

```python
optimizer = dict(type='MyOptimizer', a=a_value, b=b_value, c=c_value)
```

### 定制优化器构造器

某些模型可能具有一些特定于参数的设置以进行优化,例如 BatchNorm 层的权重衰减。
用户可以通过自定义优化器构造函数来进行那些细粒度的参数调整。

```python
from mmcv.runner.optimizer import OPTIMIZER_BUILDERS


@OPTIMIZER_BUILDERS.register_module()
class MyOptimizerConstructor:

    def __init__(self, optimizer_cfg, paramwise_cfg=None):
        pass

    def __call__(self, model):

        return my_optimizer
```

默认的优化器构造器被创建于[](https://github.com/open-mmlab/mmcv/blob/9ecd6b0d5ff9d2172c49a182eaa669e9f27bb8e7/mmcv/runner/optimizer/default_constructor.py#L11)
可被视为新优化器构造器的模板。

### 额外设定

优化器没有实现的优化技巧(trick)可通过优化器构造函数(例如,设置按参数的学习率)或钩子来实现。
下面列出了一些可以稳定训练或加快训练速度的常用设置。用户亦可通过为 MMAction2 创建 PR,发布更多设置。

- __使用梯度裁剪来稳定训练__
  一些模型需要使用梯度裁剪来剪辑渐变以稳定训练过程。 一个例子如下:

  ```python
  optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
  ```

- __使用动量调整来加速模型收敛__
  MMAction2 支持动量调整器根据学习率修改模型的动量,从而使模型收敛更快。
  动量调整程序通常与学习率调整器一起使用,例如,以下配置用于3D检测以加速收敛。
  更多细节可参考 [CyclicLrUpdater](https://github.com/open-mmlab/mmcv/blob/f48241a65aebfe07db122e9db320c31b685dc674/mmcv/runner/hooks/lr_updater.py#L327)
[CyclicMomentumUpdater](https://github.com/open-mmlab/mmcv/blob/f48241a65aebfe07db122e9db320c31b685dc674/mmcv/runner/hooks/momentum_updater.py#L130)

  ```python
  lr_config = dict(
      policy='cyclic',
      target_ratio=(10, 1e-4),
      cyclic_times=1,
      step_ratio_up=0.4,
  )
  momentum_config = dict(
      policy='cyclic',
      target_ratio=(0.85 / 0.95, 1),
      cyclic_times=1,
      step_ratio_up=0.4,
  )
  ```

## 定制学习率调整策略

在配置文件中使用默认值的逐步学习率调整,它调用 MMCV 中的 [`StepLRHook`](https://github.com/open-mmlab/mmcv/blob/f48241a65aebfe07db122e9db320c31b685dc674/mmcv/runner/hooks/lr_updater.py#L153)
此外,也支持其他学习率调整方法,如 `CosineAnnealing``Poly`。 详情可见 [这里](https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/lr_updater.py)

- Poly:

  ```python
  lr_config = dict(policy='poly', power=0.9, min_lr=1e-4, by_epoch=False)
  ```

- ConsineAnnealing:

  ```python
  lr_config = dict(
      policy='CosineAnnealing',
      warmup='linear',
      warmup_iters=1000,
      warmup_ratio=1.0 / 10,
      min_lr_ratio=1e-5)
  ```

## 定制工作流

默认情况下,MMAction2 推荐用户在训练周期中使用 “EvalHook” 进行模型验证,也可以选择 “val” 工作流模型进行模型验证。

工作流是一个形如 (工作流名, 周期数) 的列表,用于指定运行顺序和周期。其默认设置为:

```python
workflow = [('train', 1)]
```

其代表要进行一轮周期的训练。
有时,用户可能希望检查有关验证集中模型的某些指标(例如,损失,准确性)。
在这种情况下,可以将工作流程设置为

```python
[('train', 1), ('val', 1)]
```

从而将迭代运行1个训练时间和1个验证时间。

**值得注意的是**

1. 在验证周期时不会更新模型参数。
2. 配置文件内的关键词 `total_epochs` 控制训练时期数,并且不会影响验证工作流程。
3. 工作流 `[('train', 1), ('val', 1)]``[('train', 1)]` 不会改变 `EvalHook` 的行为。
   因为 `EvalHook``after_train_epoch` 调用,而验证工作流只会影响 `after_val_epoch` 调用的钩子。
   因此,`[('train', 1), ('val', 1)]``[('train', 1)]` 的区别在于,runner 在完成每一轮训练后,会计算验证集上的损失。

## 定制钩子

### 定制用户自定义钩子

#### 1. 创建一个新钩子

这里举一个在 MMAction2 中创建一个新钩子,并在训练中使用它的示例:

```python
from mmcv.runner import HOOKS, Hook


@HOOKS.register_module()
class MyHook(Hook):

    def __init__(self, a, b):
        pass

    def before_run(self, runner):
        pass

    def after_run(self, runner):
        pass

    def before_epoch(self, runner):
        pass

    def after_epoch(self, runner):
        pass

    def before_iter(self, runner):
        pass

    def after_iter(self, runner):
        pass
```

根据钩子的功能,用户需要指定钩子在训练的每个阶段将要执行的操作,比如 `before_run``after_run``before_epoch``after_epoch``before_iter``after_iter`

#### 2. 注册新钩子

之后,需要导入 `MyHook`。假设该文件在 `mmaction/core/utils/my_hook.py`,有两种办法导入它:

- 修改 `mmaction/core/utils/__init__.py` 进行导入

  新定义的模块应导入到 `mmaction/core/utils/__init__py` 中,以便注册表能找到并添加新模块:

```python
from .my_hook import MyHook
```

- 使用配置文件中的 `custom_imports` 变量手动导入

```python
custom_imports = dict(imports=['mmaction.core.utils.my_hook'], allow_failed_imports=False)
```

#### 3. 修改配置

```python
custom_hooks = [
    dict(type='MyHook', a=a_value, b=b_value)
]
```

还可通过 `priority` 参数(可选参数值包括 `'NORMAL'``'HIGHEST'`)设置钩子优先级,如下所示:

```python
custom_hooks = [
    dict(type='MyHook', a=a_value, b=b_value, priority='NORMAL')
]
```

默认情况下,在注册过程中,钩子的优先级设置为 “NORMAL”。

### 使用 MMCV 内置钩子

如果该钩子已在 MMCV 中实现,则可以直接修改配置以使用该钩子,如下所示

```python
mmcv_hooks = [
    dict(type='MMCVHook', a=a_value, b=b_value, priority='NORMAL')
]
```

### 修改默认运行的钩子

有一些常见的钩子未通过 `custom_hooks` 注册,但在导入 MMCV 时已默认注册,它们是:

- log_config
- checkpoint_config
- evaluation
- lr_config
- optimizer_config
- momentum_config

在这些钩子中,只有 log_config 具有 “VERY_LOW” 优先级,其他钩子具有 “NORMAL” 优先级。
上述教程已经介绍了如何修改 “optimizer_config”,“momentum_config” 和 “lr_config”。
下面介绍如何使用 log_config,checkpoint_config,以及 evaluation 能做什么。

#### 模型权重文件配置

MMCV 的 runner 使用 `checkpoint_config` 来初始化 [`CheckpointHook`](https://github.com/open-mmlab/mmcv/blob/9ecd6b0d5ff9d2172c49a182eaa669e9f27bb8e7/mmcv/runner/hooks/checkpoint.py#L9)

```python
checkpoint_config = dict(interval=1)
```

用户可以设置 “max_keep_ckpts” 来仅保存少量模型权重文件,或者通过 “save_optimizer” 决定是否存储优化器的状态字典。
更多细节可参考 [这里](https://mmcv.readthedocs.io/en/latest/api.html#mmcv.runner.CheckpointHook)

#### 日志配置

`log_config` 包装了多个记录器钩子,并可以设置间隔。
目前,MMCV 支持 `WandbLoggerHook``MlflowLoggerHook``TensorboardLoggerHook`
更多细节可参考[这里](https://mmcv.readthedocs.io/en/latest/api.html#mmcv.runner.LoggerHook)

```python
log_config = dict(
    interval=50,
    hooks=[
        dict(type='TextLoggerHook'),
        dict(type='TensorboardLoggerHook')
    ])
```

#### 验证配置

评估的配置将用于初始化 [`EvalHook`](https://github.com/open-mmlab/mmaction2/blob/master/mmaction/core/evaluation/eval_hooks.py#L12)
除了键 `interval` 外,其他参数,如 “metrics” 也将传递给 `dataset.evaluate()`

```python
evaluation = dict(interval=1, metrics='bbox')
```