玩转MMDetection-MMDetection中的模型框架文件及参数解读(一)

该文主要介绍完整的MMDetection包含的配置文件中的模型文件--model.py

以下代码详细逐行解读了模型文件包含的代码含义及使用

一 、特征提取网络主干

玩转MMDetection-MMDetection中的模型框架文件及参数解读(一)_第1张图片

 采用如上图所示的SwinTransformer作为特征提取网络主干,并进行以下配置。
 若想选取其他主干模型,则更改“type=‘新模型名字’ ”,且需要根据你选择的新模型对应定义新的参数,例如以下SwinTransformer作为主干的示例,以及对应参数的含义

    backbone=dict(
        type='SwinTransformer',     #主干网络(特征提取网络)采用Swin Transformer,以下为关于Swin Transformer网络参数的选取
        embed_dim=96,               #输入Swin Transformer第一层的嵌入维度,整个过程为[96, 192, 384, 768]
        depths=[2, 2, 6, 2],        #Swin Transformer四个阶段W-MSA和SW-MSA的个数
        num_heads=[3, 6, 12, 24],   #Swin Transformer四个阶段分别对应的多头数
        window_size=7,              #Swin Transformer整个阶段采用的窗口大小
        mlp_ratio=4.,               #MPL的词向量嵌入维度,默认为4
        qkv_bias=True,
        qk_scale=None,
        drop_rate=0.,
        attn_drop_rate=0.,
        drop_path_rate=0.2,
        ape=False,
        patch_norm=True,
        out_indices=(0, 1, 2, 3),
        use_checkpoint=False),

二、特征增强neck网络 

玩转MMDetection-MMDetection中的模型框架文件及参数解读(一)_第2张图片

  采用如上图所示的Feature Pyramid Network(FPN)特征金字塔作为特征提取网络主干,并进行以下配置。
 同理,若想选取其他neck,则更改“type=‘新模型名字’ ”,且需要根据你选择的新模型对应定义新的参数,例如以下FPN作为主干的示例,以及对应参数的含义,in_channels对应swin transformer四个阶段的尺度通道数,out_channels对应每个尺度的输出通道数,num_outs为输出尺度的数量,RCNN中的输出尺度会比特征提取网络多一个尺度,因此num_outs=backbone尺度数+1

    neck=dict(
        type='FPN',                     #neck特征增强采用FPN(特征金字塔)
        in_channels=[96, 192, 384, 768],#每个尺度的输入通道数
        out_channels=256,               #每个尺度的输出通道数,每个尺度都一致
        num_outs=5),                    #输出尺度的数量,RCNN中的输出尺度数量为4+1,其中4为主干网络Swin Transformer的四个尺度

 三、检测器的二阶段

一阶段:提取proposal候选框——RPN

rpn全称是region proposal network,作用是为第二阶段提供高质量的目标候选框
①anchor generator

根据给定的scales、ratios、strides,生成不同的anchor。
②anchor target generator
anchor target layer完成区分哪些anchor是为正样本(包括真实目标),哪些anchor为负样本(只包括背景)的任务,具体方法是计算anchor与ground truth的IoU。
③RPN Loss
rpn有两个任务:从众多anchor中,判断哪些anchor是正样本,哪些是负样本,即分类任务;对于正样本的anchor,回归获得真正的目标,即回归任务。所以loss由两部分组成,分类分支的随时函数和回归分支的损失函数。
④proposal generator
获得候选框的目的是为了给第二阶段提供优质的ROI框

rpn_head=dict(
        type='RPNHead',                 #采用RPN提取proposal候选框
        in_channels=256,                #输入特征图中的通道数
        feat_channels=256,              #特征图的通道数
        anchor_generator=dict(
            type='AnchorGenerator',     #anchor生成器的配置
            scales=[8],                 #就是放缩的尺度,要将宽和高按照各个scale的值放大。scales*strides
            ratios=[0.5, 1.0, 2.0],     #长短边比例
            strides=[4, 8, 16, 32, 64]),#anchor_strides代表感受野的大小,以配置文件中,anchor_strides=[4, 8, 16, 32, 64]为例。
                                        #具体来说,anchor_strides[0]就是指P2层feature map上的一个点对应到原图上的4个像素;
                                        # anchor_strides[1]就是指P3层feature map上的一个点对应到原图上的8个像素;
                                        # 以此类推……正是由于这个特性,anchor_strides也刚好代表了每一个levlel的anchor对应于原图中的基础大小。
                                        # 因此,在AnchorGenerator中,传入的anchor_strides参数被命名为base_size。
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder', #训练过程中对anchor框进行编码和解码,采用'DeltaXYWHBBoxCoder' 的框编码器
            target_means=[.0, .0, .0, .0],      #用于编码和解码框的目标均值
            target_stds=[1.0, 1.0, 1.0, 1.0]),  #用于编码和解码框的标准方差
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,在RPN中通常用于二分类吗,仅分类目标和背景,因此基本上使用sigmoid函数
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),                #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值

二阶段:对候选区域进行特征提取,送入分类器中进行种类判别——ROI

ROI全称是Region of Interest,是指对一张图片的“感兴趣区域”
①proposal target generator
在rpn产生的proposal的基础上,选择一定量(min_batch: 一般每张图选择256个proposal,或者512个proposal)的roi,作为训练第二阶段的样本,并且要设定该min_batch中正负样本的比例
②feature crop and pooling
在第一步得到的ROI上,根据ROI的大小,需要选择合适的特征层裁剪并池化得到固定大小的特征图,这个过程叫做ROI Align(ROI对齐),采用双线性插值的方式来求取像素值进而实现ROI Align

 roi_head=dict(                                                      #作为检测器的第二步
        type='StandardRoIHead',
        bbox_roi_extractor=dict(                                        #Bbox感兴趣区域的特征提取器
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),#roi层的配置,采用的ROI对齐,特征图输出大小为7,sampling_ratio指提取ROI特征时的采样率
            out_channels=256,                                                #特征的输出通道数
            featmap_strides=[4, 8, 16, 32]),                                 #多尺度特征图的步幅,应该与主干的架构保持一致,具体可参考RPN中的strides前四个
        bbox_head=dict(                                                 #RoIHead 中 box head 的配置
            type='Shared2FCBBoxHead',
            in_channels=256,                                            #bbox_head的输入通道,与bbox_roi_extractor的输出通道大小一致
            fc_out_channels=1024,                                       #全连接FC层的输出特征通道数
            roi_feat_size=7,                                            #候选区域(Region of Interest)特征的大小
            num_classes=80,                                             #分类的类别数,和你自己的数据集相匹配
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0., 0., 0., 0.],                          #用于编码和解码框的目标均值
                target_stds=[0.1, 0.1, 0.2, 0.2]),                      #编码和解码的标准方差。因为框更准确,所以值更小,常规设置时 [0.1, 0.1, 0.2, 0.2]。
            reg_class_agnostic=False,                                   #回归是否与类别无关
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,是否使用sigmoid函数
            loss_bbox=dict(type='L1Loss', loss_weight=1.0)),                 #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值

四、模型训练和测试的超参数配置

train_cfg和test_cfg的一些配置都是关于RPN和RCNN的样本部分的超参数配置,具体参数解释如下:

 train_cfg=dict(                                         #rpn 和 rcnn 训练超参数的配置
        rpn=dict(
            assigner=dict(                                  #分配正负样本分配器的配置
                type='MaxIoUAssigner',                      #选用MaxIoUAssigner
                pos_iou_thr=0.7,                            #IOU >= 0.7 作为正样本
                neg_iou_thr=0.3,                            #IOU <= 0.3 作为负样本
                min_pos_iou=0.3,                            #作为正样本的最小IOU阈值
                match_low_quality=True,                     #是否匹配低质量的框
                ignore_iof_thr=-1),                         #忽略 bbox 的 IoF 阈值
            sampler=dict(                                   #正负采样器的配置
                type='RandomSampler',                       #选用RandomSampler采样器
                num=256,                                    #需要提取样本的数量
                pos_fraction=0.5,                           #正样本占总样本数的比例
                neg_pos_ub=-1,                              #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
                add_gt_as_proposals=False),                 #采样后是否添加 GT 作为 proposal
            allowed_border=-1,                              #对有效anchor进行边界填充,-1表示不填充
            pos_weight=-1,                                  #训练期间正样本权重,-1代表不更改
            debug=False),                                   #是否设置调试(debug)模式
        rpn_proposal=dict(                                  #在训练期间生成 proposals 的配置
            nms_pre=2000,                                   #做非极大值抑制(NMS)前box的数量
            max_per_img=1000,                               #做NMS后要保留的box的数量
            nms=dict(type='nms', iou_threshold=0.7),        #NMS,其阈值为0.7
            min_bbox_size=0),                               #允许的最小 box 尺寸
        rcnn=dict(
            assigner=dict(                                  #RCNN分配正负样本
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,                            #IOU >= 0.5 作为正样本
                neg_iou_thr=0.5,                            #IOU < 0.5 作为负样本
                min_pos_iou=0.5,                            # 将 box 作为正样本的最小 IoU 阈值
                match_low_quality=True,                     #是否匹配低质量的框
                ignore_iof_thr=-1),                         #忽略 bbox 的 IoF 阈值,-1表示不忽略
            sampler=dict(                                   #正负采样器的配置
                type='RandomSampler',                       #选用RandomSampler采样器
                num=512,                                    #需要提取样本的数量
                pos_fraction=0.25,                          #正样本占总样本数的比例
                neg_pos_ub=-1,                              #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
                add_gt_as_proposals=True),                  #采样后是否添加 GT 作为 proposal
            mask_size=28,                                   #mask的大小
            pos_weight=-1,                                  #训练期间正样本权重,-1代表不更改
            debug=False)),                                  #是否设置调试(debug)模式
    test_cfg=dict(                                          #rpn 和 rcnn 测试超参数的配置
        rpn=dict(
            nms_pre=1000,                                   #做非极大值抑制(NMS)前box的数量
            max_per_img=1000,                               #做NMS后要保留的box的数量
            nms=dict(type='nms', iou_threshold=0.7),        #NMS,其阈值为0.7
            min_bbox_size=0),                               #允许的最小 box 尺寸
        rcnn=dict(
            score_thr=0.05,                                 #bbox的分数阈值
            nms=dict(type='nms', iou_threshold=0.5),        #NMS,其阈值为0.5
            max_per_img=100,                                #做NMS后要保留的box的数量
            mask_thr_binary=0.5)))                          #mask预处的阈值

以下为一个完整的模型文件代码及参数介绍mask_rcnn_swin_fpn.py

# model settings
model = dict(
    type='MaskRCNN',                #你所采用的检测器类型
    pretrained=None,
    backbone=dict(
        type='SwinTransformer',     #主干网络(特征提取网络)采用Swin Transformer,以下为关于Swin Transformer网络参数的选取
        embed_dim=96,               #输入Swin Transformer第一层的嵌入维度,整个过程为[96, 192, 384, 768]
        depths=[2, 2, 6, 2],        #Swin Transformer四个阶段W-MSA和SW-MSA的个数
        num_heads=[3, 6, 12, 24],   #Swin Transformer四个阶段分别对应的多头数
        window_size=7,              #Swin Transformer整个阶段采用的窗口大小
        mlp_ratio=4.,               #MPL的词向量嵌入维度,默认为4
        qkv_bias=True,
        qk_scale=None,
        drop_rate=0.,
        attn_drop_rate=0.,
        drop_path_rate=0.2,
        ape=False,
        patch_norm=True,
        out_indices=(0, 1, 2, 3),
        use_checkpoint=False),
    neck=dict(
        type='FPN',                     #neck特征增强采用FPN(特征金字塔)
        in_channels=[96, 192, 384, 768],#每个尺度的输入通道数
        out_channels=256,               #每个尺度的输出通道数,每个尺度都一致
        num_outs=5),                    #输出尺度的数量,RCNN中的输出尺度数量为4+1,其中4为主干网络Swin Transformer的四个尺度
    rpn_head=dict(
        type='RPNHead',                 #采用RPN提取proposal候选框
        in_channels=256,                #输入特征图中的通道数
        feat_channels=256,              #特征图的通道数
        anchor_generator=dict(
            type='AnchorGenerator',     #anchor生成器的配置
            scales=[8],                 #就是放缩的尺度,要将宽和高按照各个scale的值放大。scales*strides
            ratios=[0.5, 1.0, 2.0],     #长短边比例
            strides=[4, 8, 16, 32, 64]),#anchor_strides代表感受野的大小,以配置文件中,anchor_strides=[4, 8, 16, 32, 64]为例。
                                        #具体来说,anchor_strides[0]就是指P2层feature map上的一个点对应到原图上的4个像素;
                                        # anchor_strides[1]就是指P3层feature map上的一个点对应到原图上的8个像素;
                                        # 以此类推……正是由于这个特性,anchor_strides也刚好代表了每一个levlel的anchor对应于原图中的基础大小。
                                        # 因此,在AnchorGenerator中,传入的anchor_strides参数被命名为base_size。
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder', #训练过程中对anchor框进行编码和解码,采用'DeltaXYWHBBoxCoder' 的框编码器
            target_means=[.0, .0, .0, .0],      #用于编码和解码框的目标均值
            target_stds=[1.0, 1.0, 1.0, 1.0]),  #用于编码和解码框的标准方差
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,在RPN中通常用于二分类吗,仅分类目标和背景,因此基本上使用sigmoid函数
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),                #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
    roi_head=dict(                                                      #作为检测器的第二步
        type='StandardRoIHead',
        bbox_roi_extractor=dict(                                        #Bbox感兴趣区域的特征提取器
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),#roi层的配置,采用的ROI对齐,特征图输出大小为7,sampling_ratio指提取ROI特征时的采样率
            out_channels=256,                                                #特征的输出通道数
            featmap_strides=[4, 8, 16, 32]),                                 #多尺度特征图的步幅,应该与主干的架构保持一致,具体可参考RPN中的strides前四个
        bbox_head=dict(                                                 #RoIHead 中 box head 的配置
            type='Shared2FCBBoxHead',
            in_channels=256,                                            #bbox_head的输入通道,与bbox_roi_extractor的输出通道大小一致
            fc_out_channels=1024,                                       #全连接FC层的输出特征通道数
            roi_feat_size=7,                                            #候选区域(Region of Interest)特征的大小
            num_classes=80,                                             #分类的类别数,和你自己的数据集相匹配
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0., 0., 0., 0.],                          #用于编码和解码框的目标均值
                target_stds=[0.1, 0.1, 0.2, 0.2]),                      #编码和解码的标准方差。因为框更准确,所以值更小,常规设置时 [0.1, 0.1, 0.2, 0.2]。
            reg_class_agnostic=False,                                   #回归是否与类别无关
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),#分类分支的损失函数配置,采用CrossEntropyLoss损失,是否使用sigmoid函数
            loss_bbox=dict(type='L1Loss', loss_weight=1.0)),                 #回归分支的损失函数配置,采用L1Loss损失,给损失权重赋值
        mask_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=14, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        mask_head=dict(
            type='FCNMaskHead',
            num_convs=4,
            in_channels=256,
            conv_out_channels=256,
            num_classes=80,
            loss_mask=dict(
                type='CrossEntropyLoss', use_mask=True, loss_weight=1.0))),
    # model training and testing settings
    train_cfg=dict(                                         #rpn 和 rcnn 训练超参数的配置
        rpn=dict(
            assigner=dict(                                  #分配正负样本分配器的配置
                type='MaxIoUAssigner',                      #选用MaxIoUAssigner
                pos_iou_thr=0.7,                            #IOU >= 0.7 作为正样本
                neg_iou_thr=0.3,                            #IOU <= 0.3 作为负样本
                min_pos_iou=0.3,                            #作为正样本的最小IOU阈值
                match_low_quality=True,                     #是否匹配低质量的框
                ignore_iof_thr=-1),                         #忽略 bbox 的 IoF 阈值
            sampler=dict(                                   #正负采样器的配置
                type='RandomSampler',                       #选用RandomSampler采样器
                num=256,                                    #需要提取样本的数量
                pos_fraction=0.5,                           #正样本占总样本数的比例
                neg_pos_ub=-1,                              #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
                add_gt_as_proposals=False),                 #采样后是否添加 GT 作为 proposal
            allowed_border=-1,                              #对有效anchor进行边界填充,-1表示不填充
            pos_weight=-1,                                  #训练期间正样本权重,-1代表不更改
            debug=False),                                   #是否设置调试(debug)模式
        rpn_proposal=dict(                                  #在训练期间生成 proposals 的配置
            nms_pre=2000,                                   #做非极大值抑制(NMS)前box的数量
            max_per_img=1000,                               #做NMS后要保留的box的数量
            nms=dict(type='nms', iou_threshold=0.7),        #NMS,其阈值为0.7
            min_bbox_size=0),                               #允许的最小 box 尺寸
        rcnn=dict(
            assigner=dict(                                  #RCNN分配正负样本
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,                            #IOU >= 0.5 作为正样本
                neg_iou_thr=0.5,                            #IOU < 0.5 作为负样本
                min_pos_iou=0.5,                            # 将 box 作为正样本的最小 IoU 阈值
                match_low_quality=True,                     #是否匹配低质量的框
                ignore_iof_thr=-1),                         #忽略 bbox 的 IoF 阈值,-1表示不忽略
            sampler=dict(                                   #正负采样器的配置
                type='RandomSampler',                       #选用RandomSampler采样器
                num=512,                                    #需要提取样本的数量
                pos_fraction=0.25,                          #正样本占总样本数的比例
                neg_pos_ub=-1,                              #基于正样本数量的负样本上限,超出上限的忽略,-1表示不忽略
                add_gt_as_proposals=True),                  #采样后是否添加 GT 作为 proposal
            mask_size=28,                                   #mask的大小
            pos_weight=-1,                                  #训练期间正样本权重,-1代表不更改
            debug=False)),                                  #是否设置调试(debug)模式
    test_cfg=dict(                                          #rpn 和 rcnn 测试超参数的配置
        rpn=dict(
            nms_pre=1000,                                   #做非极大值抑制(NMS)前box的数量
            max_per_img=1000,                               #做NMS后要保留的box的数量
            nms=dict(type='nms', iou_threshold=0.7),        #NMS,其阈值为0.7
            min_bbox_size=0),                               #允许的最小 box 尺寸
        rcnn=dict(
            score_thr=0.05,                                 #bbox的分数阈值
            nms=dict(type='nms', iou_threshold=0.5),        #NMS,其阈值为0.5
            max_per_img=100,                                #做NMS后要保留的box的数量
            mask_thr_binary=0.5)))                          #mask预处的阈值
玩转MMDetection-MMDetection中的数据集文件、训练计划文件、运行信息文件及具体参数解读(二)
玩转MMDetection-MMDetection制作自己的配置文件(三)

你可能感兴趣的:(玩转MMDetection,深度学习,人工智能,python,目标检测)