• 神经网络


         VGGNetInception出现后, 学者们将卷积网络不断加深以寻求更优越的性能, 然而随着网络的加深, 网络却越发难以训练, 一方面会产生梯度消失现象; 另一方面越深的网络返回的梯度相关性会越来越差,接近于白噪声, 导致梯度更新也接近于随机扰动。

        ResNetResidual Network, 残差网络) 较好地解决了这个问题, 并获得了2015ImageNet分类任务的第一名。 此后的分类、 检测、 分割等任务也大规模使用ResNet作为网络骨架。

        ResNet的思想在于引入了一个深度残差框架来解决梯度消失问题,即让卷积网络去学习残差映射, 而不是期望每一个堆叠层的网络都完整地拟合潜在的映射(拟合函数) 。 如图3.17所示, 对于神经网络, 如果我们期望的网络最终映射为H(x), 左侧的网络需要直接拟合输出H(x),而右侧由ResNet提出的子模块, 通过引入一个shortcut(捷径) 分支, 将需要拟合的映射变为残差F(x)H(x)-xResNet给出的假设是: 相较于直接优化潜在映射H(x), 优化残差映射F(x)是更为容易的。

        在ResNet中, 上述的一个残差模块称为BottleneckResNet有不同网络层数的版本, 如18层、 34层、 50层、 101层和152层, 这里以常用的50层来讲解。 ResNet-50的网络架构如图3.18所示, 最主要的部分在于中间经历了4个大的卷积组, 而这4个卷积组分别包含了3463Bottleneck模块。 最后经过一个全局平均池化使得特征图大小变为1×1,然后进行1000维的全连接, 最后经过Softmax输出分类得分。

     

        由于F(x)+x是逐通道进行相加, 因此根据两者是否通道数相同, 存在两种Bottleneck结构。 对于通道数不同的情况, 比如每个卷积组的第一个Bottleneck, 需要利用1×1卷积对x进行Downsample操作, 将通道数变为相同, 再进行加操作。 对于相同的情况下, 两者可以直接进行相加。
        利用PyTorch实现一个带有Downsample操作的Bottleneck结构, 新建一个resnet_bottleneck.py文件, 代码如下:

       

     1 import torch.nn as nn
     2 
     3 class Bottleneck(nn.Module):
     4 
     5     def __init__(self, in_dim, out_dim, stride=1):
     6 
     7         super(Bottleneck, self).__init__()
     8         # 网路堆叠层是由1×1、 3×3、 1×1这3个卷积组成的, 中间包含BN层
     9         self.bottlenceck = nn.Sequential(
    10                 nn.Conv2d(in_dim, in_dim, 1, bias=False),
    11                 nn.BatchNorm2d(in_dim),
    12                 nn.ReLU(inplace=True),
    13                 nn.Conv2d(in_dim, in_dim, 3, 1, 1, bias=False),
    14                 nn.BatchNorm2d(in_dim),
    15                 nn.ReLU(inplace=True),
    16                 nn.Conv2d(in_dim, out_dim, 1, bias=False),
    17                 nn.BatchNorm2d(out_dim)
    18         )
    19 
    20         self.relu = nn.ReLU(inplace=True)
    21         # Downsample部分是由一个包含BN层的1×1卷积组成
    22         self.downsample = nn.Sequential(
    23                 nn.Conv2d(in_dim, out_dim, 1, 1),
    24                 nn.BatchNorm2d(out_dim)
    25         )
    26 
    27     def forward(self, x):
    28         identity = x
    29         out = self.bottlenceck(x)
    30         identity = self.downsample(x)
    31 
    32         # 将identity(恒等映射) 与网络堆叠层输出进行相加, 并经过ReLU后输出
    33         out += identity 
    34         out = self.relu(out)
    35         return out
    View Code
     1 import torch
     2 from resnet_bottleneck import Bottleneck
     3 
     4 # 实例化Bottleneck, 输入通道数为64, 输出为256, 对应第一个卷积组的第一个Bottleneck
     5 bottleneck_1_1 = Bottleneck(64, 256).cuda()
     6 print(bottleneck_1_1)
     7 # Bottleneck作为卷积堆叠层, 包含了1×1、 3×3、 1×1这3个卷积层
     8 >>  Bottleneck(
     9         (bottlenceck): Sequential(
    10             (0): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
    11             (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    12             (2): ReLU(inplace=True)
    13             (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
    14             (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    15             (5): ReLU(inplace=True)
    16             (6): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
    17             (7): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    18         )
    19         (relu): ReLU(inplace=True)
    20         # 利用Downsample结构将恒等映射的通道数变为与卷积堆叠层相同, 保证可以相加
    21         (downsample): Sequential(
    22             (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
    23             (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    24         )
    25     )
    26 
    27 input = torch.randn(1, 64, 56, 56).cuda()
    28 output = bottleneck_1_1(input) # 将输入送到Bottleneck结构中
    29 print(input.shape)
    30 >> torch.Size([1, 64, 56, 56])
    31 
    32 print(output.shape)
    33 # 相比输入, 输出的特征图分辨率没变, 而通道数变为4倍
    34 >> torch.Size([1, 256, 56, 56])
    View Code



  • 相关阅读:
    go语言编程之旅笔记5
    go语言编程之旅笔记4
    go语言编程之旅笔记3
    go语言编程之旅笔记1~2
    minikube使用记录
    Azure Sql : Could not find stored procedure 'sp_addlinkedserver'.
    Jenkins SVN WebDeploy远程服务器
    sqlserver使用cte实现某列按字符分隔成多行
    openstack安装记录
    C语言中的bzero函数
  • 原文地址:https://www.cnblogs.com/zhaopengpeng/p/13714214.html
Copyright © 2020-2023  润新知