Skip to content

Latest commit

 

History

History
347 lines (240 loc) · 11.7 KB

7_customize_runtime.md

File metadata and controls

347 lines (240 loc) · 11.7 KB

教程 7:如何自定义模型运行参数

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

定制优化方法

使用 PyTorch 内置的优化器

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

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

要修改模型的学习率,用户只需要在优化程序的配置中修改 “lr” 即可。 用户可根据 PyTorch API 文档 进行参数设置

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

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

定制用户自定义的优化器

1. 定义一个新的优化器

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

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

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 中,以便注册器能找到新模块并将其添加:

from .my_optimizer import MyOptimizer
  • 在配置中使用 custom_imports 手动导入
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” 字段定义,如下所示:

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

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

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

定制优化器构造器

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

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

默认的优化器构造器被创建于, 可被视为新优化器构造器的模板。

额外设定

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

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

    optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
  • 使用动量调整来加速模型收敛 MMAction2 支持动量调整器根据学习率修改模型的动量,从而使模型收敛更快。 动量调整程序通常与学习率调整器一起使用,例如,以下配置用于3D检测以加速收敛。 更多细节可参考 CyclicLrUpdaterCyclicMomentumUpdater

    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。 此外,也支持其他学习率调整方法,如 CosineAnnealingPoly。 详情可见 这里

  • Poly:

    lr_config = dict(policy='poly', power=0.9, min_lr=1e-4, by_epoch=False)
  • ConsineAnnealing:

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

定制工作流

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

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

workflow = [('train', 1)]

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

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

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

值得注意的是

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

定制钩子

定制用户自定义钩子

1. 创建一个新钩子

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

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_runafter_runbefore_epochafter_epochbefore_iterafter_iter

2. 注册新钩子

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

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

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

from .my_hook import MyHook
  • 使用配置文件中的 custom_imports 变量手动导入
custom_imports = dict(imports=['mmaction.core.utils.my_hook'], allow_failed_imports=False)

3. 修改配置

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

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

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

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

使用 MMCV 内置钩子

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

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

checkpoint_config = dict(interval=1)

用户可以设置 “max_keep_ckpts” 来仅保存少量模型权重文件,或者通过 “save_optimizer” 决定是否存储优化器的状态字典。 更多细节可参考 这里

日志配置

log_config 包装了多个记录器钩子,并可以设置间隔。 目前,MMCV 支持 WandbLoggerHookMlflowLoggerHookTensorboardLoggerHook。 更多细节可参考这里

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

验证配置

评估的配置将用于初始化 EvalHook。 除了键 interval 外,其他参数,如 “metrics” 也将传递给 dataset.evaluate()

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