1. 简介
1.1 配置文件主要内容
- model
- Dataloader
- train_dataloader
- val_dataloader
- test_dataloader
- Evaluator
- val_evaluator
- test_evaluator
- Configuration
- optim_wrapper
- Hooks
- default_hooks
- custom_hooks
1. 2 配置文件名称含义
{algorithm name}_{model component names [component1]_[component2]_[...]}-[version id]_[norm setting]_
[data preprocessor type]_{training settings}_{training dataset information}_
{testing dataset information}.py
- 文件名分为 8 个部分,其中 4 个必填部分、4 个可选部分。 每个部分用 _ 连接,每个部分内的单词应该用 - 连接。{} 表示必填部分,[] 表示选填部分。
- {algorithm name}: 算法的名称。 它可以是检测器名称,例如 yolov5, yolov6, yolox 等。
- {component names}: 算法中使用的组件名称,如 backbone、neck 等。
- [version_id] (可选): 由于 YOLO 系列算法迭代速度远快于传统目标检测算法,因此采用 version id 来区分不同子版本之间的差异。
- [norm_setting] (可选):
- bn 表示 Batch Normalization
- syncbn 表示 Synchronized Batch Normalization。
- [data preprocessor type] (可选): 数据预处理类型
- {training settings}: 训练设置的信息,例如 batch 大小、数据增强、损失、参数调度方式和训练最大轮次/迭代。
- {gpu x batch_per_gpu}: GPU 数和每个 GPU 的样本数。bN 表示每个 GPU 上的 batch 大小为 N。例如 4xb8 是 4 个 GPU 每个 GPU 8 张图的缩写。如果没有注明,默认为 8 卡每卡 2 张图。
- {schedule}: 训练方案。
- {training dataset information}: 训练数据集,例如 coco, cityscapes, voc-0712, wider-face, balloon。
- [testing dataset information] (可选): 测试数据集,用于训练和测试在不同数据集上的模型配置。 如果没有注明,则表示训练和测试的数据集类型相同
- 例子:
yolov5_s-v61_syncbn_8xb16-300e_coco.py
- 上述例子的详细说明:
- yolov5_s:
- deepen_factor=0.33
- widen_factor=0.5,
- 通过deepen_factor和widen_factor来控制模型的大小
- yolov5_m:
- deepen_factor = 0.67
- widen_factor = 0.75
- yolov5_l:
- deepen_factor = 1.0
- widen_factor = 1.0
- v61:YOLOv5 的 6.0 以后的版本采用 6x6 Conv 层作为第一个下采样层,而 3.0 版本采用 Focus 层作为第一个下采样层
- 8xb16:表示使用 8 个 gpu 每个 gpu 16 张图,并训练 300 个 epoch
- fast:不标 fast 默认使用 mmdet.DetDataPreprocessor,而 fast 表示调用 YOLOv5DetDataPreprocessor 并配合 yolov5_collate 进行数据预处理,训练速度较快(不慢于yolov5官方),但是对多任务处理的灵活性较低
- 300e: 表示训练 300 个 epoch
- coco: 表示 COCO2017 目标检测数据集。
2. 配置文件内容
2.1 重要参数
- 深度的缩放因子deepen_factor和宽度的缩放因子widen_factor:控制模型的大小
img_scale = (640, 640)
deepen_factor = 0.33
widen_factor = 0.5
max_epochs = 300
save_epoch_intervals = 10
train_batch_size_per_gpu = 16
train_num_workers = 8
val_batch_size_per_gpu = 1
val_num_workers = 2
2.2 模型(model)配置
- 使用model字段来配置检测算法的组件
- backbone
- neck
- head
- data_preprocessor
- 负责对 dataloader 输出的每一批数据进行预处理
- 预处理包括:颜色空间变换,归一化,to cuda,pad 成一样大小方便组成 batch
- train_cfg:设置训练组件的超参数
- test_cfg:设置测试组件的超参数
anchors = [[(10, 13), (16, 30), (33, 23)],
[(30, 61), (62, 45), (59, 119)],
[(116, 90), (156, 198), (373, 326)]]
strides = [8, 16, 32]
model = dict(
type='YOLODetector',
data_preprocessor=dict(
type='mmdet.DetDataPreprocessor',
mean=[0., 0., 0.],
std=[255., 255., 255.],
bgr_to_rgb=True),
backbone=dict(
type='YOLOv5CSPDarknet',
deepen_factor=deepen_factor,
widen_factor=widen_factor,
norm_cfg=dict(type='BN', momentum=0.03, eps=0.001),
act_cfg=dict(type='SiLU', inplace=True)),
neck=dict(
type='YOLOv5PAFPN',
deepen_factor=deepen_factor,
widen_factor=widen_factor,
in_channels=[256, 512, 1024],
out_channels=[256, 512, 1024],
num_csp_blocks=3,
norm_cfg=dict(type='BN', momentum=0.03, eps=0.001),
act_cfg=dict(type='SiLU', inplace=True)),
bbox_head=dict(
type='YOLOv5Head',
head_module=dict(
type='YOLOv5HeadModule',
num_classes=80,
in_channels=[256, 512, 1024],
widen_factor=widen_factor,
featmap_strides=[8, 16, 32],
num_base_priors=3),
prior_generator=dict(
type='mmdet.YOLOAnchorGenerator',
base_sizes=anchors,
strides=strides),
),
test_cfg=dict(
multi_label=True,
nms_pre=30000,
score_thr=0.001,
nms=dict(type='nms',
iou_threshold=0.65),
max_per_img=300))
2.3 Dataloader
- 在使用执行器进行训练、测试、验证时,我们需要配置 Dataloader 。构建数据 dataloader 需要设置:
- 数据集(dataset)
- 数据处理流程(data pipeline)
- Dataloader包含dataset, dataset包含pipeline
2.3.1 训练Dataloader (train_dataloader)
dataset_type = 'CocoDataset'
data_root = 'data/coco/'
file_client_args = dict(backend='disk')
pre_transform = [
dict(type='LoadImageFromFile',
file_client_args=file_client_args),
dict(type='LoadAnnotations',
with_bbox=True)
]
albu_train_transforms = [
dict(type='Blur', p=0.01),
dict(type='MedianBlur', p=0.01),
dict(type='ToGray', p=0.01),
dict(type='CLAHE', p=0.01)
]
train_pipeline = [
*pre_transform,
dict(type='Mosaic',
img_scale=img_scale,
pad_val=114.0,
pre_transform=pre_transform),
dict(type='YOLOv5RandomAffine',
max_rotate_degree=0.0,
max_shear_degree=0.0,
scaling_ratio_range=(0.5, 1.5),
border=(-img_scale[0] // 2, -img_scale[1] // 2),
border_val=(114, 114, 114)),
dict(type='mmdet.Albu',
transforms=albu_train_transforms,
bbox_params=dict(
type='BboxParams',
format='pascal_voc',
label_fields=['gt_bboxes_labels', 'gt_ignore_flags']),
keymap={'img': 'image',
'gt_bboxes': 'bboxes'}),
dict(type='YOLOv5HSVRandomAug'),
dict(type='mmdet.RandomFlip', prob=0.5),
dict( type='mmdet.PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape', 'flip',
'flip_direction'))
]
train_dataloader = dict(
batch_size=train_batch_size_per_gpu,
num_workers=train_num_workers,
persistent_workers=True,
pin_memory=True,
sampler=dict(
type='DefaultSampler',
shuffle=True),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='annotations/instances_train2017.json',
data_prefix=dict(img='train2017/'),
filter_cfg=dict(filter_empty_gt=False, min_size=32),
pipeline=train_pipeline))
2.3.1 验证和评测Dataloader (val_dataloader+test_dataloader)
- 评测和验证dataloader是一样的
- YOLOv5 测试阶段采用 Letter Resize 的方法来将所有的测试图像统一到相同尺度,进而有效保留了图像的长宽比。因此我们在验证和评测时,都采用相同的数据流进行推理。
test_pipeline = [
dict(
type='LoadImageFromFile',
file_client_args=file_client_args),
dict(type='YOLOv5KeepRatioResize',
scale=img_scale),
dict(
type='LetterResize',
scale=img_scale,
allow_scale_up=False,
pad_val=dict(img=114)),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='mmdet.PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor', 'pad_param'))
]
val_dataloader = dict(
batch_size=val_batch_size_per_gpu,
num_workers=val_num_workers,
persistent_workers=True,
pin_memory=True,
drop_last=False,
sampler=dict(
type='DefaultSampler',
shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
test_mode=True,
data_prefix=dict(img='val2017/'),
ann_file='annotations/instances_val2017.json',
pipeline=test_pipeline,
batch_shapes_cfg=dict(
type='BatchShapePolicy',
batch_size=val_batch_size_per_gpu,
img_size=img_scale[0],
size_divisor=32,
extra_pad_ratio=0.5)))
test_dataloader = val_dataloader
2.4 评测器(val_evaluator/test_evaluator)
- 评测器:用于计算训练模型在验证和测试数据集上的指标。评测器的配置由一个或一组评价指标(Metric)配置组成:
val_evaluator = dict(
type='mmdet.CocoMetric',
proposal_nums=(100, 1, 10),
ann_file=data_root + 'annotations/instances_val2017.json',
metric='bbox',
)
test_evaluator = val_evaluator
- 如果要保存在测试数据集上的检测结果,则可以像这样编写配置:
test_dataloader = dict(
batch_size=1,
num_workers=2,
persistent_workers=True,
drop_last=False,
sampler=dict(type='DefaultSampler', shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file=data_root + 'annotations/image_info_test-dev2017.json',
data_prefix=dict(img='test2017/'),
test_mode=True,
pipeline=test_pipeline))
test_evaluator = dict(
type='mmdet.CocoMetric',
ann_file=data_root + 'annotations/image_info_test-dev2017.json',
metric='bbox',
format_only=True,
outfile_prefix='./work_dirs/coco_detection/test')
2.5 训练、验证和测试配置(train_cfg, val_cfg, test_cfg)
- MMEngine 的 Runner 使用 Loop 来控制训练,验证和测试过程。
- 用户可以使用这些字段设置:
max_epochs = 300
save_epoch_intervals = 10
train_cfg = dict(
type='EpochBasedTrainLoop',
max_epochs=max_epochs,
val_interval=save_epoch_intervals)
val_cfg = dict(type='ValLoop')
test_cfg = dict(type='TestLoop')
- MMEngine 也支持动态评估间隔,例如你可以在前面 280 epoch 训练阶段中,每间隔 10 个 epoch 验证一次,到最后 20 epoch 训练中每隔 1 个 epoch 验证一次,则配置写法为:
max_epochs = 300
save_epoch_intervals = 10
train_cfg = dict(
type='EpochBasedTrainLoop',
max_epochs=max_epochs,
val_interval=save_epoch_intervals,
dynamic_intervals=[(280, 1)])
val_cfg = dict(type='ValLoop')
test_cfg = dict(type='TestLoop')
2.6 优化相关配置 (optim_wrapper)
- optim_wrapper 是配置优化相关设置的字段。优化器封装(OptimWrapper)不仅提供了优化器的功能,还支持梯度裁剪、混合精度训练等功能
optim_wrapper = dict(
type='OptimWrapper',
optimizer=dict(
type='SGD',
lr=0.01,
momentum=0.937,
weight_decay=0.0005,
nesterov=True,
batch_size_per_gpu=train_batch_size_per_gpu),
clip_grad=None,
constructor='YOLOv5OptimizerConstructor')
- param_scheduler 字段
- 用于配置参数调度器(Parameter Scheduler)来调整优化器的超参数(例如学习率和动量)。
- 用户可以组合多个调度器来创建所需的参数调整策略。
- 在参数调度器教程和参数调度器 API 文档 中查找更多信息。
- 在 YOLOv5 中,参数调度实现比较复杂,难以 param_scheduler 实现。所以采用了 YOLOv5ParamSchedulerHook 来实现(见下节),这样做更简单但是通用性较差。
2.7 钩子配置 (default_hooks, custom_hooks)
- 用户可以在训练、验证和测试循环上添加钩子,以便在运行期间插入一些操作。配置中有两种不同的钩子字段:
- default_hooks
- custom_hooks
2.7.1 default_hooks
- default_hooks是一个字典,用于配置运行时必须使用的钩子。这些钩子具有默认优先级,如果未设置,runner 将使用默认值。如果要禁用默认钩子,用户可以将其配置设置为 None。
default_hooks = dict(
param_scheduler=dict(
type='YOLOv5ParamSchedulerHook',
scheduler_type='linear',
lr_factor=0.01,
max_epochs=max_epochs),
checkpoint=dict(
type='CheckpointHook',
interval=save_epoch_intervals,
max_keep_ckpts=3))
2.7.2 custom_hooks
- custom_hooks 是一个列表。用户可以在这个字段中加入自定义的钩子,例如 EMAHook。
custom_hooks = [
dict(
type='EMAHook',
ema_type='ExpMomentumEMA',
momentum=0.0001,
update_buffers=True,
priority=49)
]
2.8 运行相关配置
default_scope = 'mmyolo'
env_cfg = dict(
cudnn_benchmark=True,
mp_cfg=dict(
mp_start_method='fork',
opencv_num_threads=0),
dist_cfg=dict(backend='nccl'),
)
vis_backends = [dict(type='LocalVisBackend')]
visualizer = dict(
type='mmdet.DetLocalVisualizer', vis_backends=vis_backends, name='visualizer')
log_processor = dict(
type='LogProcessor',
window_size=50,
by_epoch=True)
log_level = 'INFO'
load_from = None
resume = False