• 神经网络


    前面几节的网络骨架, 如VGGNetResNet等, 虽从各个角度出发提升了物体检测性能, 但究其根本是为ImageNet的图像分类任务而设计的。 而图像分类与物体检测两个任务天然存在着落差, 分类任务侧重全图的特征提取, 深层的特征图分辨率很低; 而物体检测需要定位出物体位置, 特征图分辨率不宜过小, 因此造成了以下两种缺陷:

       ·大物体难以定位: 对于FPN等网络, 大物体对应在较深的特征图上检测, 由于网络较深时下采样率较大, 物体的边缘难以精确预测, 增加了回归边界的难度。

      ·小物体难以检测: 对于传统网络, 由于下采样率大造成小物体在较深的特征图上几乎不可见; FPN虽从较浅的特征图来检测小物体, 但浅层的语义信息较弱, 且融合深层特征时使用的上采样操作也会增加物体检测的难度。

       针对以上问题, 旷视科技提出了专为物体检测设计的DetNet结构,引入了空洞卷积, 使得模型兼具较大感受野与较高分辨率, 同时避免了3.6节中FPN的多次上采样, 实现了较好的检测效果。

    DetNet的网络结构如图3.22所示, 仍然选择性能优越的ResNet-50作为基础结构, 并保持前4stageResNet-50相同, 具体的结构细节有以下3点:

       ·引入了一个新的Stage 6, 用于物体检测。 Stage 5Stage 6使用了DetNet提出的Bottleneck结构, 最大的特点是利用空洞数为23×3卷积取代了步长为23×3卷积.

      ·Stage 5Stage 6的每一个Bottleneck输出的特征图尺寸都为原图的, 通道数都为256, 而传统的Backbone通常是特征图尺寸递减, 通道数递增.

      ·在组成特征金字塔时, 由于特征图大小完全相同, 因此可以直接从右向左传递相加, 避免了上一节的上采样操作。 为了进一步融合各通道的特征, 需要对每一个阶段的输出进行1×1卷积后再与后一Stage传回的特征相加。

     DetNet这种精心设计的结构, 在增加感受野的同时, 获得了较大的特征图尺寸, 有利于物体的定位。 与此同时, 由于各Stage的特征图尺寸相同, 避免了上一节的上采样, 既一定程度上降低了计算量, 又有利于小物体的检测。

       DetNetBottleneck的细节如图3.23所示, 左侧的两个Bottleneck ABottleneck B分别对应图3.22AB, 右侧的为原始的ResNet残差结构。 DetNetResNet两者的基本思想都是卷积堆叠层与恒等映射的相加, 区别在于DetNet使用了空洞数为23×3卷积, 这样使得特征图尺寸保持不变, 而ResNet是使用了步长为23×3卷积。 B相比于A, 在恒等映射部分增加了一个1×1卷积, 这样做可以区分开不同的Stage, 并且实验发现这种做法对于特征金字塔式的检测非常重要
    .

     使用PyTorch来实现DetNet的两个Bottleneck结构AB, 新建一个detnet_bott-leneck.py文件, 代码如下:

     1 import torch
     2 from torch import  nn
     3 
     4 class DetBottleneck(nn.Module):
     5 
     6     # 初始化时extra为False时为Bottleneck A, 为True时则为Bottleneck B
     7     def __init__(self, inplaces, planes, stride=1, extra=False):
     8 
     9         super(DetBottleneck, self).__init__()
    10         # 构建连续3个卷积层的Bottleneck 
    11         self.bottleneck = nn.Sequential(
    12                 nn.Conv2d(inplaces, planes, 1, bias =False),
    13                 nn.BatchNorm2d(planes),
    14                 nn.ReLU(inplace=True),
    15                 nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=2, dilation=2, bias=False),
    16                 nn.BatchNorm2d(planes),
    17                 nn.ReLU(inplace=True),
    18                 nn.Conv2d(planes, planes, 1, bias=False),
    19                 nn.BatchNorm2d(planes)
    20         )
    21     
    22         self.relu = nn.ReLU(inplace=True)
    23         self.extra = extra
    24 
    25         # Bottleneck B的1×1卷积
    26         if self.extra:
    27             self.extra_conv = nn.Sequential(
    28                 nn.Conv2d(inplaces, planes, 1, bias=False),
    29                 nn.BatchNorm2d(planes)
    30             )
    31     
    32     def forward(self, x):
    33         # 对于Bottleneck B来讲, 需要对恒等映射增加卷积处理, 与ResNet类似
    34         if self.extra:
    35             indentity = self.extra_conv(x)
    36         else:
    37             indentity = x
    38         out = self.bottleneck(x)
    39         out += indentity
    40         out = self.relu(out)
    41 
    42         return out 
    View Code
     1 import torch
     2 from detnet_bottleneck import DetBottleneck
     3 
     4 bottleneck_b = DetBottleneck(1024, 256, 1, True).cuda()
     5 print(bottleneck_b)
     6 >> DetBottleneck(
     7   (bottleneck): Sequential(
     8     (0): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
     9     (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    10     (2): ReLU(inplace=True)
    11     (3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2), dilation=(2, 2), bias=False)
    12     (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    13     (5): ReLU(inplace=True)
    14     (6): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    15     (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    16   )
    17   (relu): ReLU(inplace=True)
    18   (extra_conv): Sequential(
    19     (0): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    20     (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    21   )
    22 )
    23 
    24 bottleneck_a1 = DetBottleneck(256,256).cuda()
    25 print(bottleneck_a1)
    26 >> 
    27 DetBottleneck(
    28   (bottleneck): Sequential(
    29     (0): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    30     (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    31     (2): ReLU(inplace=True)
    32     (3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2), dilation=(2, 2), bias=False)
    33     (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    34     (5): ReLU(inplace=True)
    35     (6): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    36     (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    37   )
    38   (relu): ReLU(inplace=True)
    39 )
    40 
    41 
    42 bottleneck_a2 = DetBottleneck(256, 256).cuda()
    43 print(bottleneck_a2)
    44 >> DetBottleneck(
    45   (bottleneck): Sequential(
    46     (0): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    47     (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    48     (2): ReLU(inplace=True)
    49     (3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(2, 2), dilation=(2, 2), bias=False)
    50     (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    51     (5): ReLU(inplace=True)
    52     (6): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    53     (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    54   )
    55   (relu): ReLU(inplace=True)
    56 )
    57 
    58 input = torch.randn(1, 1024, 14, 14).cuda()
    59 
    60 # 将input作为某一层的特征图, 依次传入Bottleneck B、 A1与A2三个模块
    61 output1 = bottleneck_b(input)
    62 output2 = bottleneck_a1(output1)
    63 output3 = bottleneck_a2(output2)
    64 
    65 # 三个Bottleneck输出的特征图大小完全相同
    66 print(output1.shape)
    67 >> torch.Size([1, 256, 14, 14])
    68 print(output2.shape)
    69 >> torch.Size([1, 256, 14, 14])
    70 print(output3.shape)
    71 >> torch.Size([1, 256, 14, 14])
    View Code
  • 相关阅读:
    5.集合(3)——Map集合
    4.集合(3)——List集合
    2.初窥集合类1
    1.正则表达式1
    (13)JSON
    (12)表单验证
    Wpf实现TreeSelect多选
    Wpf实现TreeSelect
    Wpf登录验证方式(5)-推理拼图的实现
    Wpf登录验证方式(4)-语序点选的实现
  • 原文地址:https://www.cnblogs.com/zhaopengpeng/p/13741477.html
Copyright © 2020-2023  润新知