MMsegmentation文档学习

1.了解配置

config文件结构:

config/_base_下有4种基本组件类型:

dataset

model

schedule

default_runtime

 

同一文件夹下的所有配置,建议只具有一个原始配置,所有其他配置从原始配置继承,这样继承级别的最大值为3

 

为了便于理解,如果用户在DeepLabV3的基础上进行一些修改,建议用户可以先通过继承基本的DeepLabV3结构,然后再配置文件中修改必要的字段

_base_ = ../deeplabv3/deeplabv3_r50_512x1024_40ki_cityscapes.py

 

如果要建立一个不与任何现有方法共享结构的全新方法,可以在configs下创建一个新文件夹xxnet

 

Config命名格式:

 

{model}_{backbone}_[misc]_[gpu x batch_per_gpu]_{resolution}_{schedule}_{dataset}

 

{xxx}是必填字段,[yyy]是可选字段。

{model}:型号类型等pspdeeplabv3等。

{backbone}:骨干类型,例如r50(ResNet-50),x101(ResNeXt-101)。

[misc]:杂项设置/模型的插件,例如dconvgcbattentionmstrain

[gpu x batch_per_gpu]8x2默认使用GPU和每个GPU的样本。

{schedule}:训练时间表,20ki意味着20k次迭代。

{dataset}:数据集cityscapesvoc12augade

 

SyncBN:

SyncBN即在数据并行分布式训练时,将各显卡上分配的数据汇总到一起进行规范化处理,也就是计算所有数据全局的均值和方差。按照沐神的说法,如果分别计算均值和方差,就需要做两次数据同步。可以分布求全局的xi的和与xi²的和。这样就只需要做一次数据同步。

 

requires_grad是Pytorch中通用数据结构Tensor的一个属性,用于说明当前量是否需要在计算中保留对应的梯度信息,以线性回归为例,容易知道权重w和偏差b为需要训练的对象,为了得到最合适的参数值,我们需要设置一个相关的损失函数,根据梯度回传的思路进行训练。

MMsegmentation文档学习_第1张图片

 

DeepLab V3的示例

# model settings
norm_cfg = dict(type='SyncBN', requires_grad=True)  # 分割通常使用SyncBN
model = dict(
    type='EncoderDecoder',  # 分割器名称
    pretrained='open-mmlab://resnet50_v1c',  # 加载ImageNet预训练的backbone
    backbone=dict(
        type='ResNetV1c',  # backbone的类型
        depth=50,  # backbone的深度,一般用50,101
        num_stages=4,  # backbone的阶段数
        out_indices=(0, 1, 2, 3),  # 每个阶段生成的输出特征图的索引
        dilations=(1, 1, 2, 4),  # 每层的膨胀率
        strides=(1, 2, 1, 1),  # 每层的步幅
        norm_cfg=norm_cfg,  # 规范层的配置
        norm_eval=False,  # 是否冻结BN中的统计信息
        style='pytorch',  # 主干的样式,“ pytorch”表示第2步的步幅为3x3卷积,“ caffe”表示第2步的步幅为1x1卷积
        contract_dilation=True),  # 当扩张> 1时,是否收缩第一层扩张。
    decode_head=dict(
        type='ASPPHead',  # 解码器的类型,请参阅mmseg / models / decode_heads了解可用选项。
        in_channels=2048,  # 解码器头输入通道数
        in_index=3,  # 选择特征图的索引
        channels=512,  # 解码器头的中间通道数
        dilations=(1, 12, 24, 36),
        dropout_ratio=0.1,  # 在最终分类层之前的dropout率
        num_classes=19,  # 分割类别的数量,通常对于城市景观为19,对于VOC为21,对于ADE20k为150。
        norm_cfg=norm_cfg,
        align_corners=False,  # 用于在解码时调整大小
        loss_decode=dict(  # 解码器损失函数的配置
            type='CrossEntropyLoss',  # 用于分割的损失函数的类型
            use_sigmoid=False,  # 是否使用sigmode激活函数
            loss_weight=1.0)),  # 解码器的损失权重
    auxiliary_head=dict(
        type='FCNHead',  # auxiliary_head(辅助头)的类型,请参阅mmseg / models / decode_heads了解可用选项。
        in_channels=1024,  # 辅助头的输入通道数
        in_index=2,  # 选择特征图索引
        channels=256,  # 解码器的中间通道
        num_convs=1,  # FCNHead的卷积数,在auxiliary_head通常是1
        concat_input=False,  # 是否将convs的输出与分类器之前的输入进行拼接
        dropout_ratio=0.1,  # 最终分类器之前的dropout率
        num_classes=19,  #
        norm_cfg=norm_cfg,  # norm层的配置
        align_corners=False,  # 用于在解码时调整大小
        loss_decode=dict(
            type='CrossEntropyLoss',
            use_sigmoid=False,
            loss_weight=0.4)),  # Loss weight of auxiliary head, which is usually 0.4 of decode head
    # model training and testing settings
    train_cfg=dict(),  # train_cfg目前仅是一个占位符
    test_cfg=dict(mode='whole'))  # 测试模块,‘whole’:整个图像全卷积测试,‘sliding’:裁剪图像

# dataset settings
dataset_type = 'CityscapesDataset'  # 数据集类型,将用于定义数据集
data_root = 'data/cityscapes/'  # 数据的根路径
img_norm_cfg = dict(  # 图像归一化配置以对输入图像进行归一化
    mean=[123.675, 116.28, 103.53],  # 用于预训练预训练骨干模型的平均值
    std=[58.395, 57.12, 57.375],  # 用于预训练预训练骨干模型的标准方差
    to_rgb=True)  # 用于预训练预训练骨干模型的图像通道顺序
crop_size = (512, 1024)  # 训练时的图像剪裁大小
train_pipeline = [  # 训练通道
    dict(type='LoadImageFromFile'),  # 从文件加载图像的第一个通道
    dict(type='LoadAnnotations'),  # 为当前图像加载注释的第二个通道
    dict(type='Resize',  # 增强通道以调整图像的大小及其注释
         img_scale=(2048, 1024),  # 最大图像比例
         ratio_range=(0.5, 2.0)),  # 扩大比率的范围
    dict(type='RandomCrop',  # 增强通道从当前图像中随机裁剪一patch
         crop_size=crop_size,  # patch的大小
         cat_max_ratio=0.75),  # 单个类别可以占用的最大面积比
    dict(type='RandomFlip',  # 翻转图像及其注释的增强通道
         prob=0.5),  # 翻转的比例或概率
    dict(type='PhotoMetricDistortion'),  # 增强通道,通过多种光度学方法使当前图像失真
    dict(type='Normalize',  # 标准化输入图像的增强通道
         **img_norm_cfg),
    dict(type='Pad',  # 将图像填充到指定大小的增强通道
         size=crop_size,  # 填充的输出大小
         pad_val=0,  # 图片的填充值
         seg_pad_val=255),  # 'gt_semantic_seg'的填充值
    dict(type='DefaultFormatBundle'),  # 默认格式捆绑包,用于收集管道中的数据
    dict(type='Collect',  # 决定应将数据中的哪些键传递给分割器的管道
         keys=['img', 'gt_semantic_seg']),
]
test_pipeline = [
    dict(type='LoadImageFromFile'),  # 第一个从文件路径加载图像的管道
    dict(
        type='MultiScaleFlipAug',  # 封装测试时间扩展的封装
        img_scale=(2048, 1024),  # 确定用于调整管道大小的最大测试规模
        # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75],#更改为多规模测试
        flip=False,  # 测试期间是否翻转图像
        transforms=[
            dict(type='Resize',  # 使用调整大小的增强Use resize augmentation
                 keep_ratio=True),  # 是否保持高宽比,此处设置的img_scale将被以上设置的img_scale取代
            dict(type='RandomFlip'),  # 以为RandomFlip是在管道中添加的,当flip = False时不使用
            dict(type='Normalize',  # 规范化配置,值来自img_norm_cfg
                 **img_norm_cfg),
            dict(type='ImageToTensor',  # 将图像转换为张量
                 keys=['img']),
            dict(type='Collect',  # 收集必要密钥以进行测试的Collect管道
                 keys=['img']),
        ])
]
data = dict(
    samples_per_gpu=2,  # 单个GPU的批处理大小
    workers_per_gpu=2,  # 为每个GPU预取数据
    train=dict(  # 训练数据集配置
        type=dataset_type,  # 数据集类型,有关详细信息,请参考mmseg / datasets /
        data_root=data_root,  # 数据集的位置
        img_dir='leftImg8bit/train',  # 数据集的图像目录
        ann_dir='gtFine/train',  # 数据集的注释目录
        pipeline=train_pipeline),  # 管道,这是由之前创建的train_pipeline传递的
    val=dict(
        type=dataset_type,  # 验证数据集配置
        data_root=data_root,
        img_dir='leftImg8bit/val',
        ann_dir='gtFine/val',
        pipeline=test_pipeline),  # 管道由之前创建的test_pipeline传递
    test=dict(
        type=dataset_type,
        data_root=data_root,
        img_dir='leftImg8bit/val',
        ann_dir='gtFine/val',
        pipeline=test_pipeline))

# yapf:disable
log_config = dict(  # 配置注册记录器钩子
    interval=50,  # 间隔打印日志
    hooks=[
        dict(type='TextLoggerHook', by_epoch=False),
        # dict(type='TensorboardLoggerHook')#还支持Tensorboard记录器
    ])
# yapf:enable
dist_params = dict(backend='nccl')  # 参数设置分布式训练,也可以设置端口
log_level = 'INFO'  # 日志级别
load_from = None  # 从给定路径将模型加载为预训练模型。 这不会恢复训练
resume_from = None  # 从给定路径恢复检查点,保存检查点后,训练将从迭代中恢复
workflow = [('train',
             1)]  # Workflow for runner [('train',1)]表示只有一个工作流程,名为'train'的工作流程只执行一次。
# 工作流程根据`runner.max_iters`进行了40000次迭代训练模型。
cudnn_benchmark = True  # 是否使用cudnn_benchmark加快速度,只适用于固定输入大小

# optimizer
optimizer = dict(  # 用于构建优化器的Config,支持PyTorch中的所有优化器,其参数也与PyTorch中的参数相同
    type='SGD',  # 优化程序的类型,
    # 请参阅https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/optimizer/default_constructor.py#L13了解更多信息
    lr=0.01,  # 优化器的学习率,请参阅PyTorch文档中参数的详细用法
    momentum=0.9,  # 动量
    weight_decay=0.0005)  # SGD的重量衰减
optimizer_config = dict()  # 用于构建优化程序挂钩的配置,
# 有关实现的详细信息,请参阅https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/optimizer.py#L8。
# learning policy
lr_config = dict(policy='poly',
                 # scheduler的策略还支持Step,CosineAnnealing,Cyclic等。
                 # 请参阅https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/lr_updater.py#所支持的LrUpdater的详细信息。 L9。
                 power=0.9,  # 多项式衰减的幂
                 min_lr=1e-4,  # 稳定训练的最低学习率
                 by_epoch=False)  # 是否按epoch计数
# runtime settings
runner = dict(type='IterBasedRunner',  # 要使用的运行程序类型(即IterBasedRunner或EpochBasedRunner)
              max_iters=40000)  # 迭代总数。 对于EpochBasedRunner使用`max_epochs`
checkpoint_config = dict(
    # 进行配置以设置检查点挂钩,有关实现请参阅https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py
    by_epoch=False,  # 是否按epoch计数
    interval=4000)  # 保存间隔
evaluation = dict(  # 用于构建评估挂钩的配置。 有关详细信息,请参考mmseg / core / evaulation / eval_hook.py
    interval=4000,  # 评估间隔
    metric='mIoU')  # 评估指标

2.自定义数据集

 

最简单的方法就是重组数据,以此作为数据集

 

文件结构的示例:

MMsegmentation文档学习_第2张图片

  • 通过混合数据集来自定义数据集

MMSegmentation支持这种混合数据集以进行训练。目前,它支持合并和重复数据集。

混合数据集有以下几种方式

  • 重复数据集

使用RepeatDataset包装器来重复数据集,以下是重复数据集Dataset_A示例

 

dataset_A_train = dict(

        type='RepeatDataset',

        times=N,

        dataset=dict(  # This is the original config of Dataset_A  数据集A的原始配置

            type='Dataset_A',

            ...

            pipeline=train_pipeline

        )

    )

连接数据集

两种方法:

(1)如果要连接的数据集属于同一类型,但带有不同的注释文件,则可以如下连接数据集配置

1.连接两个ann_dir

MMsegmentation文档学习_第3张图片

2.连接两个split

MMsegmentation文档学习_第4张图片

3.同时连接两个ann_dir和两个split

MMsegmentation文档学习_第5张图片

这种情况下,ann_dir_1和ann_dir_2对应于split_1.txt和split_2.txt

 

(2)如果要连接的数据集不同,则使用如下的配置

MMsegmentation文档学习_第6张图片

重复Dataset_A N次,Dataset_B M次,分别再连接每个重复的数据集

MMsegmentation文档学习_第7张图片

3.自定义数据通道

数据管道设计

资料载入

  • LoadImageFromFile

添加img,img_shape,ori_shape

 

  • LoadAnnotations

添加gt_semantic_seg,seg_fields

 

预处理

Resize

  • add:scale, scale_idx, pad_shape, scale_factor, keep_ratio
  • update:img, img_shape, *seg_fields

 

RandomFlip

  • add: flip
  • update: img, *seg_fields

 

Pad

  • add: pad_fixed_size, pad_size_divisor
  • update: img, pad_shape, *seg_fields

 

RandomCrop

  • update: img, pad_shape, *seg_fields

 

Normalize

  • add: img_norm_cfg
  • update: img

 

SegRescale

  • update: gt_semantic_seg

 

PhotoMetricDistortion

  • update: img

 

 

格式设定

ToTensor

  • update: specified by keys

 

ImageToTensor

  • update: specified by keys

 

Transpose

  • update: specified by keys

 

ToDataContainer

  • update: specified by fields

 

DefaultFormatBundle

  • update: img, gt_semantic_seg

 

Collect

  • add: img_meta (the keys of img_meta is specified by meta_keys)

img_meta的键由meta_keys指定

  • remove: all other keys except for those specified by keys

除按键指定的按键外的其他所有按键

 

 

测试时间增强

MultiScaleFlipAug

 

 

扩展和使用自定义通道

1.再任意文件中编写新的通道my_pipeline.py,他以一个dict作为输入并返回一个dict

 

from mmseg.datasets import PIPELINES

@PIPELINES.register_module()
class MyTransform:

def __call__(self, results):
        results[
'dummy'] = True
        return results

 

2.导入新类

from .my_pipeline import MyTransform

 

3.再配置文件中使用它

img_norm_cfg = dict(
    mean
=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
crop_size
= (512, 1024)
train_pipeline
= [
   
dict(type='LoadImageFromFile'),
   
dict(type='LoadAnnotations'),
   
dict(type='Resize', img_scale=(2048, 1024), ratio_range=(0.5, 2.0)),
   
dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
   
dict(type='RandomFlip', flip_ratio=0.5),
   
dict(type='PhotoMetricDistortion'),
   
dict(type='Normalize', **img_norm_cfg),
   
dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255),
   
dict(type='MyTransform'),
   
dict(type='DefaultFormatBundle'),
   
dict(type='Collect', keys=['img', 'gt_semantic_seg']),
]

 

 

4.自定义模型

 

自定义优化器

假设要添加一个优化器名为MyOptimizer,现有一个arguments包含a,b,c

我们在mmseg/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)

 

然后在mmseg/core/optimizer/__init__.py中添加这个模块,目的是注册器会找到这个新模块并且添加它

from .my_optimizer import MyOptimizer

 

你可以用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)

 

 

自定义优化器构造函数

某些模型可能具有一些特定于参数的设置以进行优化,用户可以通过自定义优化器构造函数来进行那些细粒度(具体是什么类型的狗)的参数调整

from mmcv.utils import build_from_cfg

from mmcv.runner import OPTIMIZER_BUILDERS
from .cocktail_optimizer import CocktailOptimizer

@OPTIMIZER_BUILDERS.register_module
class CocktailOptimizerConstructor(object):

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

def __call__(self, model):

return my_optimizer

 

开发新组件

MMSegmentation中主要有两种类型的组件

  • backbone:通常是卷积网络堆栈,以提取特征图,例如ResNet,HRNet。
  • head:用于语义分割图解码的组件。

 

添加新的backbone

1.创建一个新文件mmseg/models/backbones/resnet.py

import torch.nn as nn

from ..registry import BACKBONES

@BACKBONES.register_module
class ResNet(nn.Module):

def __init__(self, arg1, arg2):
       
pass

def forward(self, x):  # should return a tuple
        pass

def init_weights(self, pretrained=None):
       
pass

 

 

1.在mmseg/models/backbones/__init__.py中导入模块

from .resnet import ResNet

 

1.在自己的配置文件中使用

model = dict(
   
...
    backbone=dict(
       
type='ResNet',
        arg1
=xxx,
        arg2
=xxx),
   

 

添加新的heads

在mmsegmentation中,作者为所有的segmentation head提供了基本的BaseDecodeHead,所有新实现的decode heads应该源于它

 

首先,在mmseg/models/decode_heads/psp_head.py中添加一个新的decode head,实现decode head我们需要实现以下三个函数:

@HEADS.register_module()
class PSPHead(BaseDecodeHead):

def __init__(self, pool_scales=(1, 2, 3, 6), **kwargs):
       
super(PSPHead, self).__init__(**kwargs)

def init_weights(self):

def forward(self, inputs):

 

然后需要在mmseg/models/decode_heads/__init__.py中添加这个模块使得相应的注册表找到并加载

 

norm_cfg = dict(type='SyncBN', requires_grad=True)
model
= dict(
   
type='EncoderDecoder',
    pretrained
='pretrain_model/resnet50_v1c_trick-2cccc1ad.pth',
    backbone
=dict(
       
type='ResNetV1c',
        depth
=50,
        num_stages
=4,
        out_indices
=(0, 1, 2, 3),
        dilations
=(1, 1, 2, 4),
        strides
=(1, 2, 1, 1),
        norm_cfg
=norm_cfg,
        norm_eval
=False,
        style
='pytorch',
        contract_dilation
=True),
    decode_head
=dict(
       
type='PSPHead',
        in_channels
=2048,
        in_index
=3,
        channels
=512,
        pool_scales
=(1, 2, 3, 6),
        dropout_ratio
=0.1,
        num_classes
=19,
        norm_cfg
=norm_cfg,
        align_corners
=False,
        loss_decode
=dict(
           
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)))

 

 

添加新的损失函数

用户添加新的损失函数MyLoss需要在mmseg/models/losses/my_loss.py(需要新建)中实现,

装饰器weighted_loss使得对每一个函数的损失得以加权

import torch
import torch.nn as nn

from ..builder import LOSSES
from .utils import weighted_loss

@weighted_loss
def my_loss(pred, target):
   
assert pred.size() == target.size() and target.numel() > 0
    loss = torch.abs(pred - target)
   
return loss

@LOSSES.register_module
class MyLoss(nn.Module):

def __init__(self, reduction='mean', loss_weight=1.0):
       
super(MyLoss, self).__init__()
       
self.reduction = reduction
       
self.loss_weight = loss_weight

def forward(self,
                pred,
                target,
                weight
=None,
                avg_factor
=None,
                reduction_override
=None):
       
assert reduction_override in (None, 'none', 'mean', 'sum')
        reduction
= (
            reduction_override
if reduction_override else self.reduction)
        loss
= self.loss_weight * my_loss(
            pred, target, weight, reduction
=reduction, avg_factor=avg_factor)
       
return loss

 

然后用户需要在mmseg/models/losses/__init__.py中添加

from .my_loss import MyLoss, my_loss

 

使用它需要修改loss_xxx字段,然后需要修改在head中的loss_decode字段,loss_weight可以被用来平衡多重损失

loss_decode=dict(type='MyLoss', loss_weight=1.0)

 

5.训练技巧

 

Backbone与Heads的学习率不同

 

在语义分割中,一些方法使头部的LR大于主干的LR,以实现更好的性能或更快的收敛。

 

在MMSegmentation中,您可以在配置中添加以下行,以使头部的LR达到主干的10倍。

optimizer=dict(
    paramwise_cfg
= dict(
        custom_keys
={
           
'head': dict(lr_mult=10.)}))

 

 

Online Hard Example Mining (OHEM)

 

_base_ = './pspnet_r50-d8_512x1024_40k_cityscapes.py'
model=dict(
    decode_head
=dict(
        sampler
=dict(type='OHEMPixelSampler', thresh=0.7, min_kept=100000)) )

 

 

 

类平衡损失(在一组样本中不同类别的样本量差异非常大)

对于类别分布不平衡的数据集,您可以更改每个类别的损失权重。这是城市景观数据集的示例

_base_ = './pspnet_r50-d8_512x1024_40k_cityscapes.py'
model=dict(
    decode_head
=dict(
        loss_decode
=dict(
           
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0,
           
# DeepLab used this class weight for cityscapes
            class_weight=[0.8373, 0.9180, 0.8660, 1.0345, 1.0166, 0.9969, 0.9754,
                       
1.0489, 0.8786, 1.0023, 0.9539, 0.9843, 1.1116, 0.9037,
                       
1.0865, 1.0955, 1.0865, 1.1529, 1.0507])))

 

 

6.自定义运行是设置

自定义自我实现的优化器

(1)定义一个新的优化器

假设要添加一个优化器名为MyOptimizer,现有一个arguments包含a,b,c

我们需要在一个文件中实现一个新的优化器比如mmseg/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)将优化器添加到注册表

然后在mmseg/core/optimizer/__init__.py中添加这个模块,注册器会找到这个新模块并且添加它

from .my_optimizer import MyOptimizer

 

使用custom_imports在配置文件中手动导入

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

 

该模块mmseg.core.optimizer.my_optimizer将在程序开始时导入,MyOptimizer然后自动注册该类。请注意,仅MyOptimizer应导入包含该类的包。 mmseg.core.optimizer.my_optimizer.MyOptimizer 无法直接导入。

 

实际上,只要模块根目录可以位于中,用户就可以使用这种导入方法使用完全不同的文件目录结构PYTHONPATH

 

(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.utils import build_from_cfg

from mmcv.runner.optimizer import OPTIMIZER_BUILDERS, OPTIMIZERS
from mmseg.utils import get_root_logger
from .my_optimizer import MyOptimizer

@OPTIMIZER_BUILDERS.register_module()
class MyOptimizerConstructor(object):

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

def __call__(self, model):

return my_optimizer

 

 

 

附加设置

一些可以稳定训练或加快训练速度的常用设置

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

optimizer_config = dict(
    _delete_
=True, grad_clip=dict(max_norm=35, norm_type=2))

 

使用动量进度表来加速模型收敛:我们支持动量进度表根据学习率修改模型的动量,这可以使模型更快地收敛。动量调度程序通常与LR调度程序一起使用,例如,以下配置用于3D检测以加速收敛。

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,
)

 

 

自定义训练计划

一般情况下我们将逐步学习率与40k/80k计划一起使用,mmsegmentation支持许多学习率计划,例如CosineAnnealing和Poly计划

Step schedule:

lr_config = dict(policy='step', step=[9, 10])

 

ConsineAnnealing schedule:

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

 

 

自定义工作流程

工作流是(阶段,时期)的列表,用于指定运行顺序和时期。默认情况下,它设置为

workflow = [('train', 1)]

这意味着要进行1个时期的训练。有时,用户可能想检查有关验证集中模型的某些指标(例如,损失,准确性)。在这种情况下,我们可以将工作流程设置为

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

运行1个训练时间和1个验证时间。

 

 

注意事项:

1.val epoch期间不会更新模型的参数

2.配置中的关键字total_epochs仅控制训练时期的数量,不会影响验证工作流程

3.工作流[('train',1),('val',1)]和[('train',1)]不会更改EvalHook的行为,因为EvalHook由after_train_epoch调用,并且验证工作流仅影响被调用的钩子 通过after_val_epoch。 因此,[('train',1),('val',1)]和[('train',1)]之间的唯一区别是,跑步者将在每个训练时期后根据验证集计算损失

 

 

自定义挂钩

使用MMCV中实现的挂钩

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

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

 

修改默认的运行时挂钩

有一些未通过注册的常见钩子custom_hooks,它们是

log_config

checkpoint_config

评估

lr_config

optimizer_config

动量配置

 

在这些钩子中,只有记录器钩子的优先级为VERY_LOW,其他钩子的优先级为NORMAL。 上述教程已经介绍了如何修改optimizer_config,momentum_config和lr_config。 在这里,我们揭示了如何使用log_config,checkpoint_config和评估功能。

 

 

检查点配置

MMCV运行程序将用于checkpoint_config初始化CheckpointHook。

checkpoint_config = dict(interval=1)

 

用户可以设置max_keep_ckpts为仅保存少量检查点,或者通过决定是否存储优化器的状态字典save_optimizer。参数的更多详细信息在这里

 

 

日志配置

 

该log_config包装的多个记录器的钩和能够设定的时间间隔。现在MMCV支持WandbLoggerHook,MlflowLoggerHook和TensorboardLoggerHook。详细用法可以在doc中找到。

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

 

评估配置

评估配置将用于初始化EvalHook。 除键间隔外,其他参数(例如metric)将传递给数据集。evaluate()

 

evaluation = dict(interval=1, metric='mIoU')

 

 

 

 

 

 

你可能感兴趣的:(Openmmlab,pytorch,神经网络,深度学习)