前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Detectron2学习五:build_backbone_model配置及实现流程

Detectron2学习五:build_backbone_model配置及实现流程

原创
作者头像
CV_Learner
修改2019-12-16 11:19:28
5.5K1
修改2019-12-16 11:19:28
举报
文章被收录于专栏:CV_Learn

本文主要讲build_backbone_model的配置及创建流程,目的则是希望大家看完本章节后能够对detectron2中模型创建及使用有清晰的认识,便于后续自定义网络层。若有需要补充希望大家在评论中提出。

build_model调用位置如下:

调用顺序:----->表示调用该文件夹下相应的函数,即:函数调用路径。

代码语言:javascript
复制
class DefaultTrainer(SimpleTrainer):
    model = self.build_model(cfg)
                    ------->##/detectron2/engine/defaults.py
                           def build_model(cls,cfg):
                               model = build_model(cfg)
                                        ---------->##detectron2/modeling/meta_arch/build.py
                                                   def build_model(cfg):
                                                       meta_arch = cfg.MODEL.META_ARCHITECTURE
                                                       return META_ARCH_REGISTRY.get(meta_arch)(cfg)

接下来则是基于配置文件夹中相应的模型配置参数进行相应模块的调用。所有的网络配置基本都是可以通过配置文件进行完成,个人认为,这是学习Detectron2框架过程中最需要学习和掌握的一个重要的环节。

一、基本参数配置

其他默认参数配置可参见/detectron2/config/defaults.py文件

本章节以/configs/PascalVOC-Detection/faster_rcnn_R_50_FPN.yaml为例进行阐述。

代码语言:javascript
复制
####faster_rcnn_R_50_FPN.yaml
_BASE_: "../Base-RCNN-FPN.yaml"
MODEL:
  WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl"
  MASK_ON: False
  RESNETS:
    DEPTH: 50
  ROI_HEADS:
    NUM_CLASSES: 20
...
代码语言:javascript
复制
###../Base-RCNN-FPN.yaml
MODEL:
  META_ARCHITECTURE: "GeneralizedRCNN"
  BACKBONE:
    NAME: "build_resnet_fpn_backbone"
  RESNETS:
    OUT_FEATURES: ["res2", "res3", "res4", "res5"]
  FPN:
    IN_FEATURES: ["res2", "res3", "res4", "res5"]
  ANCHOR_GENERATOR:
    SIZES: [[32], [64], [128], [256], [512]]  # One size for each in feature map
    ASPECT_RATIOS: [[0.5, 1.0, 2.0]]  # Three aspect ratios (same for all in feature maps)
...

基于配置信息可知该网络的注册名称为:GeneralizedRCNN (在搭建网络之前,首先要注册一个META_ARCH_REGISTRY,方便在配置文件中使用,如果要进行检测任务的话,可在GeneralizedRCNN机制下进行修改)

(利用全局搜索,定位到该类所在的文件为/detectron2/modeling/meta_arch/rcnn.py 。该文件中主要包含两类,GeneralizedRCNN和ProposalNetwork。

代码语言:javascript
复制
__all__ = ["GeneralizedRCNN", "ProposalNetwork"]

@META_ARCH_REGISTRY.register()
class GeneralizedRCNN(nn.Module):
    """
    Generalized R-CNN. Any models that contains the following three components:
    1. Per-image feature extraction (aka backbone)  图像特征提取主要是图像数据、通道、均值、方差的处理。
    2. Region proposal generation  ##候选区域的生成
    3. Per-region feature extraction and prediction ##特征提取及预测
    """
    
@META_ARCH_REGISTRY.register()
class ProposalNetwork(nn.Module):

从该配置信息中能获取到什么信息呢?配置的网络结构是怎样的呢?

  • 基网络为resnet50的结构,对res2,res3,res4,res5四层进行FPN操作。

而其中阶段名称'res2','res3'从哪获取的呢?与之关联设置的参数又是怎样的呢?

在文件/detectron2/modeling/backbone/resnet.py中设置默认的每个阶段的配置参数和输出名称如下:

代码语言:javascript
复制
 ##depth为配置文件中配置的MODEL.RESNETS.DEPTH
 ##当前默认支持res50,res101,res152三种网络结构,分为4个阶段,,每个阶段的配置blocks的个数如下
num_blocks_per_stage = {50: [3, 4, 6, 3], 101: [3, 4, 23, 3], 152: [3, 8, 36, 3]}[depth]

##4个阶段的输出名称配置如下:注意的是该名称与外面网络配置参数的名称要保持一致,否则找不到
##out_features为配置文件中的MODEL.RESNETS.OUT_FEATURES
stages = []
out_stage_idx = [{"res2": 2, "res3": 3, "res4": 4, "res5": 5}[f] for f in out_features]

#########题外延伸#############
resnet的配置不一定要配置为4个阶段,可根据需求进行适当修改。任意举例如:
num_blocks_per_stage={50,[2,3,4,3,4]}  ##5个阶段,意味着可以有5个特征层的输出
out_stage_idx=[{"res2": 2, "res3": 3, "res4": 4, "res5": 5,“res6”:6}[f] for f in out_features]
ResNet网络层
ResNet网络层
  • anchor计算:每个特征层产生anchor的aspect_ratio都是一样的[0.5,1.0,2.0],该情况可根据自己需要进行配置参数。
代码语言:javascript
复制
MODEL:
  ANCHOR_GENERATOR:
    SIZES: [[32], [64], [128], [256], [512]]  # One size for each in feature map
    ASPECT_RATIOS: [[0.5, 1.0, 2.0],[0.5, 1.0, 2.0,0.33,3.0],[0.5, 1.0, 2.0,0.33,3.0],[0.5, 1.0, 2.0],[0.5, 1.0, 2.0]]
    ##此处的aspect_ratio为实际运算时需要的比例值。与caffe里面实现的不同。
    ##caffe里面则是外部设置aspect_ratio=2,3,flip=True,实际内部计算时的值为:1,1,2,3,1/2,1/3.具体计算可自行百度
    ##个人认为caffe的这种实现方式比较方便。可修改相应源代码实现该操作。

二、GeneralizedRCNN中网络结构创建顺序和调用接口。

三、 build_backbone参数设置及实现流程

代码语言:javascript
复制
##参数设置
MODEL:
  BACKBONE:
    NAME: "build_resnet_fpn_backbone"    
  RESNETS:
    OUT_FEATURES: ["res2", "res3", "res4", "res5"]
  FPN:
    IN_FEATURES: ["res2", "res3", "res4", "res5"]

(相同道理,全局搜索build_resnet_fpn_backbone,如果有能运行起来demo的话,那就单步跟进最方便)

改环节主要包含两个部分:

  • 创建基网络模型build_resnet_backbone,基于配置参数MODEL.RESNETS建立网络结构,设置输出层、冻结层、可变性卷积层、层的stride、kernel_size、dilation、in_channles、out_channels等的操作。具体实现见代码,实现起来比较清晰。

主要的网络结果如下:

resnet基本网络结构--BottleneckBlock如下:

带有deformable-conv的网络结构--DeformBottleneckBlock如下:(deformable conv的具体实现后续有时间在深入了解)

当前该框架支持deformV1和deformV2两个版本,相应参数设置如下:

代码语言:javascript
复制
# Apply Deformable Convolution in stages
# Specify if apply deform_conv on Res2, Res3, Res4, Res5
_C.MODEL.RESNETS.DEFORM_ON_PER_STAGE = [False, False, False, False]
# Use True to use modulated deform_conv (DeformableV2, https://arxiv.org/abs/1811.11168);
# Use False for DeformableV1.
_C.MODEL.RESNETS.DEFORM_MODULATED = False
# Number of groups in deformable conv.
_C.MODEL.RESNETS.DEFORM_NUM_GROUPS = 1
  • FPN操作

现在先来回顾下FPN论文中的主要结构如下:

(a)图像金字塔,即将图像做成不同的scale,然后不同scale的图像生成对应的不同scale的特征。这种方法的缺点在于增加了时间成本。有些算法会在测试时候采用图像金字塔。

(b)像SPP net,Fast RCNN,Faster RCNN是采用这种方式,即仅采用网络最后一层的特征。

(c)像SSD(Single Shot Detector)采用这种多尺度特征融合的方式,没有上采样过程,即从网络不同层抽取不同尺度的特征做预测,这种方式不会增加额外的计算量。作者认为SSD算法中没有用到足够低层的特征(在SSD中,最低层的特征是VGG网络的conv4_3),而在作者看来足够低层的特征对于检测小物体是很有帮助的。

(d)FPN中的网络结构,顶层特征通过上采样和低层特征做融合,而且每层都是独立预测的。

在FPN中特征融合的方式,先对当前特征的维度进行操作,然后与上采样得到的特征进行融合(横向连接),对融合后的特征再接一个3*3的卷积网络,目的则是消除上采样的混叠效应(aliasing effect).

先看下该函数的官方定义说明:

代码语言:javascript
复制
class FPN(Backbone):
    """
    This module implements Feature Pyramid Network.
    It creates pyramid features built on top of some input feature maps.
    """
    返回的结果dict[str->Tensor]
    与输入特征层in_features名称对应,输出的名称:['p2','p3','p4','p5','p6']
    其中最底层的特征输出'p6',该层是通过对'p5'层进行下采样操作(max_pool(stride=2,kernel=1,padding=0))得到的。

    def __init__(
        self, bottom_up, in_features, out_channels, norm="", top_block=None, fuse_type="sum"
    ):
        """
        Args:
            bottom_up (Backbone): 输入的基网络,
            in_features (list[str]): 进行特征融合的层['res2','res3','res4','res5']]
            out_channels (int): number of channels in the output feature maps.
            norm (str): the normalization to use.
            top_block (nn.Module or None): 最后输出的层
            fuse_type (str): 特征融合时的计算方式,'sum','avg'
            #####其中,'avg':上采样后的feature map与当前融合的feature map 进行element_wise求平均操作((value1+value2/2))
                      'sum':上采样后的feature map与当前融合的feature map 进行element_wise求和操作
        """

代码中上采样操作采用插值操作,默认使用最近邻,除此之外,还支持其他很多类型,可自由选择。

代码语言:javascript
复制
top_down_features = F.interpolate(prev_features, scale_factor=2, mode="nearest")

######

def interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None):
    
    The modes available for resizing are: `nearest`, `linear` (3D-only),
    `bilinear` (4D-only), `trilinear` (5D-only), `area`

    Args:
        input (Tensor): the input tensor,4D(N*C*H*W),5D(N*C*D*H*W)
        size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]):
            output spatial size.
        scale_factor (float or Tuple[float]): multiplier for spatial size. Has to match input size if it is a tuple.
        mode (string): algorithm used for upsampling:
            'nearest' | 'linear' | 'bilinear' | 'trilinear' | 'area'. Default: 'nearest'
        align_corners (bool, optional): if True, the corner pixels of the input
            and output tensors are aligned, and thus preserving the values at
            those pixels. This only has effect when :attr:`mode` is `linear`,
            `bilinear`, or `trilinear`. Default: False

    .. warning::
        With ``align_corners = True``, the linearly interpolating modes
        (`linear`, `bilinear`, and `trilinear`) don't proportionally align the
        output and input pixels, and thus the output values can depend on the
        input size. This was the default behavior for these modes up to version
        0.3.1. Since then, the default behavior is ``align_corners = False``.
        See :class:`~torch.nn.Upsample` for concrete examples on how this
        affects the outputs.

    .. include:: cuda_deterministic_backward.rst
    """

理解通FPN实现流程,再看代码就相对比较简单了,此处就不上传代码,想看请直接移步文件/detectron2/modeling/backbone/fpn.py文件中

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档