自定义运行¶
在本教程中,我们将介绍一些关于如何设置项目自定义运行的方法。
循环(Loop)¶
Loop
表示训练、验证或测试的工作流,我们使用 train_cfg
,val_cfg
和 test_cfg
来构建 Loop
。
示例:
# Use EpochBasedTrainLoop to train 200 epochs.
train_cfg = dict(type='EpochBasedTrainLoop', max_epochs=200)
MMEngine定义了几个基本的循环。如果定义的循环不满足需求,用户可以实现自定义的循环。
钩子(Hook)¶
在学习创建自定义钩子之前,建议先学习文件engine.md中关于钩子的基本概念。
步骤1:创建一个新的钩子¶
根据钩子的目的,您需要根据期望的钩子点实现相应的函数。
例如,如果您想根据训练迭代次数和另外两个超参数的值在每个训练迭代后修改超参数的值,您可以实现一个类似以下的钩子:
# Copyright (c) OpenMMLab. All rights reserved.
from typing import Optional, Sequence
from mmengine.hooks import Hook
from mmselfsup.registry import HOOKS
from mmselfsup.utils import get_model
@HOOKS.register_module()
class NewHook(Hook):
"""Docstring for NewHook.
"""
def __init__(self, a: int, b: int) -> None:
self.a = a
self.b = b
def before_train_iter(self,
runner,
batch_idx: int,
data_batch: Optional[Sequence[dict]] = None) -> None:
cur_iter = runner.iter
get_model(runner.model).hyper_parameter = self.a * cur_iter + self.b
步骤2:导入新的钩子¶
然后我们需要确保 NewHook
已经被导入。假设 NewHook
在 mmselfsup/engine/hooks/new_hook.py
中,按照以下方式修改 mmselfsup/engine/hooks/__init__.py
文件:
...
from .new_hook import NewHook
__all__ = [..., NewHook]
步骤3:修改配置文件¶
custom_hooks = [
dict(type='NewHook', a=a_value, b=b_value)
]
您还可以按照以下方式设置钩子的优先级:
custom_hooks = [
dict(type='NewHook', a=a_value, b=b_value, priority='ABOVE_NORMAL')
]
默认情况下,在注册时,钩子的优先级被设置为 NORMAL
。
优化器(Optimizer)¶
在自定义优化器配置之前,建议先学习文件engine.md中有关优化器的基本概念。
以下是SGD优化器的示例:
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0001)
我们支持PyTorch中的所有优化器。更多细节,请参见MMEngine优化器文档。
优化器包装器¶
优化器包装器提供了单精度训练和不同硬件的自动混合精度训练的统一接口。以下是一个 optim_wrapper
配置的示例:
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0001)
optim_wrapper = dict(type='OptimWrapper', optimizer=optimizer)
此外,如果您想要应用自动混合精度训练,可以修改上面的配置,例如:
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0001)
optim_wrapper = dict(type='AmpOptimWrapper', optimizer=optimizer)
AmpOptimWrapper
的 loss_scale
的默认设置为 dynamic
。
构造器¶
构造器旨在构建优化器、优化器包装器并自定义不同层的超参数。配置文件中 optim_wrapper
的 paramwise_cfg
键控制此自定义。
有关示例和详细信息,请参见MMEngine优化器文档。
此外,我们可以使用 custom_keys
为不同模块设置不同的超参数。
以下是MAE的 optim_wrapper
示例。以下配置将 pos_embed
, mask_token
, cls_token
模块和名称包含ln
和bias
的那些层的权重衰减的乘法乘数设置为 0。在训练过程中,这些模块的权重衰减将是 weight_decay * decay_mult
。
optimizer = dict(
type='AdamW', lr=1.5e-4 * 4096 / 256, betas=(0.9, 0.95), weight_decay=0.05)
optim_wrapper = dict(
type='OptimWrapper',
optimizer=optimizer,
paramwise_cfg=dict(
custom_keys={
'ln': dict(decay_mult=0.0),
'bias': dict(decay_mult=0.0),
'pos_embed': dict(decay_mult=0.),
'mask_token': dict(decay_mult=0.),
'cls_token': dict(decay_mult=0.)
}))
此外,对于某些特定设置,我们可以使用布尔类型的参数来控制优化过程或参数。例如,以下是SimCLR的示例配置:
optimizer = dict(type='LARS', lr=0.3, momentum=0.9, weight_decay=1e-6)
optim_wrapper = dict(
type='OptimWrapper',
optimizer=optimizer,
paramwise_cfg=dict(
custom_keys={
'bn': dict(decay_mult=0, lars_exclude=True),
'bias': dict(decay_mult=0, lars_exclude=True),
# bn layer in ResNet block downsample module
'downsample.1': dict(decay_mult=0, lars_exclude=True),
}))
在 LARS
优化器中,我们有 lars_exclude
选项来决定指定的层是否应用 LARS
优化方法。
调度器(Scheduler)¶
在自定义调度器配置之前,建议先学习 MMEngine文档 中关于调度器的基本概念。
以下是一个调度器的示例:
param_scheduler = [
dict(
type='LinearLR',
start_factor=1e-4,
by_epoch=True,
begin=0,
end=40,
convert_to_iter_based=True),
dict(
type='CosineAnnealingLR',
T_max=360,
by_epoch=True,
begin=40,
end=400,
convert_to_iter_based=True)
]
注意: 当您更改 train_cfg
中的 max_epochs
时,请确保同时修改 param_scheduler
中的参数。