图像分类篇:pytorch实现ResNet

一、ResNet详解 

ResNet网络是在2015年由微软实验室提出的,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名,获得COCO数据集中目标检测第一名,图像分类第一名。

图像分类篇:pytorch实现ResNet_第1张图片

 在ResNet网络中的亮点:

  • 搭建超深层网络(突破1000层)
  • 提出Residual结构(残差结构)
  • 使用Batch Normalization加速训练(丢弃Dropout)

下图是ResNet34层模型的结构简图:

在这里插入图片描述

 在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与池化层进行堆叠得到的,一般我们会觉得网络越深,特征信息越丰富,模型效果越来越好。但是实验证明,当网络堆叠到一定深度时,会出现两个问题:

1.梯度消失或梯度爆炸

  • 梯度消失:是指当每一层的误差梯度小于1时,在反向传播过程中,每一层都要乘以一个小于1的数,结果网络层数越深,梯度就越趋近于0,导致梯度消失。
  • 梯度爆炸:反之,若每一层的误差梯度大于1,每一层都要乘以一个大于1的数,结果网络层数越深,梯度就越大

2.退化问题(degradation problem)

在解决了梯度消失、爆炸问题后,仍然存在深层网络的效果可能比浅层网络差的现象。从以往的经验来看,网络的深度对模型的性能好坏影响至关重要,当网络层数增加后,模型可以进行更加复杂的特征提取,所以当模型的网络层数越深时,理论上是可以取得更好的结果的。下图是20层网络与56层网络在CIFAR-10上的误差对比,但更深的网络结构其性能一定更好吗?

图像分类篇:pytorch实现ResNet_第2张图片

 从上图可以直观看出,56层网络比20层网络效果还要差,意味着深度网络出现了退化问题:当网络深度增加时,网络准确度出现饱和,甚至出现下降。这不是过拟合问题,因为56层网络的训练误差同样高。

 对于以上两个问题,ResNet论文提出了Residual结构来解决,下图是使用residual结构的卷积网络,可以看到随着网络的不断加深,效果并没有变差,而是变的更好了。(虚线是train error,实线是test error)

在这里插入图片描述

3.ResNet中的残差结构

为了解决深层网络中的退化问题,可以人为的让神经网络某些层跳过下一层神经元的连接,隔层相连,弱化每层之间的强联系,这些神经网络被称为残差网络。残差网络由许多各层相连的神经元子模块组成,我们称之为残差块(Residual block)。实际应用中,残差结构的short cut不一定是隔一层连接,也可以中间隔多层,ResNet所提出的残差网络中就是隔多层。

跟VggNet类似,ResNet也有多个不同层的版本,而残差结构也有两种对应浅层和深层网络:

ResNet 残差结构
浅层网络 ResNet18/34 BasicBlock
深层网络 ResNet50/101/152 Bottleneck

下图中左侧残差结构称为 BasicBlock,右侧残差结构称为Bottleneck:

在这里插入图片描述

对于深层的Bottleneck,1x1的卷积核起到降维和升维(特征矩阵深度)的作用,同时可以大大减少网络参数。可以计算一下,假设两个残差结构的输入特征和输出特征矩阵的深度都是256维,如下图:

在这里插入图片描述

 那么两个残差结构所需的参数为:

  • 左侧:3x3x256x256+3x3x256x256=179648
  • 右侧:1x1x256x64+3x3x64x64+1x1x64x256=69632

注:CNN参数个数=卷积核尺寸x卷积核深度x卷积核组数=卷积核尺寸x输入特征矩阵深度x输出特征矩阵深度

为什么深层网络要使用右侧的残差结构呢。因为,右侧的残差结构能够减少网络参数与运算量。同样输入、输出一个channel为256的特征矩阵,如果使用左侧的残差结构需要大约1170648个参数,但如果使用右侧的残差结构只需要69632个参数。明显搭建深层网络时,使用右侧的残差结构更合适。

4.降维时的short cut

下图时ResNet18层网络,可以发现有些残差块的short cut是实线的,而有些是虚线的。这些虚线的short cut上通过1x1的卷积核进行了维度处理:特征矩阵在长宽方向降采样,深度方向调整成下一层残差结构所需的channel。

在这里插入图片描述

下图是原论文给出的不同深度的ResNet网络结构配置,注意表中的残差结构给出了主分支上卷积核的大小与卷积核个数,表中 残差块×N 表示将该残差结构重复N次。

在这里插入图片描述

 原文的表注中已说明,conv3_x, conv4_x, conv5_x所对应的一系列残差结构的第一层残差结构都是虚线残差结构。因为这一系列残差结构的第一层都有调整输入特征矩阵shape的使命(将特征矩阵的高和宽缩减为原来的一半,将深度channel调整成下一层残差结构所需要的channel)

需要注意的是,对于ResNet50/101/152,其实conv2_x所对应的一系列残差结构的第一层也是虚线残差结构,因为它需要调整输入特征矩阵的channel。根据表格可知通过3x3的max pool之后输出的特征矩阵shape应该是[56, 56, 64],但conv2_x所对应的一系列残差结构中的实线残差结构它们期望的输入特征矩阵shape是[56, 56, 256](因为这样才能保证输入输出特征矩阵shape相同,才能将捷径分支的输出与主分支的输出进行相加)。所以第一层残差结构需要将shape从[56, 56, 64] --> [56, 56, 256]。注意,这里只调整channel维度,高和宽不变(而conv3_x, conv4_x, conv5_x所对应的一系列残差结构的第一层虚线残差结构不仅要调整channel还要将高和宽缩减为原来的一半)。

下面是 ResNet 18/34 和 ResNet 50/101/152 具体的实线/虚线残差结构图:

ResNet 18/34,如下图所示,该残差结构的主分支是由两层3x3的卷积层组成,而残差结构右侧的连接线是shortcut分支也称捷径分支(注意为了让主分支上的输出矩阵能够与我们捷径分支上的输出矩阵进行相加,必须保证这两个输出特征矩阵有相同的shape)。如果刚刚仔细观察了ResNet34网络结构图的同学,应该能够发现图中会有一些虚线的残差结构。在原论文中作者只是简单说了这些虚线残差结构有降维的作用,并在捷径分支上通过1x1的卷积核进行降维处理。而下图右侧给出了详细的虚线残差结构,注意下每个卷积层的步距stride,以及捷径分支上的卷积核的个数(与主分支上的卷积核个数相同)。

在这里插入图片描述

ResNet 50/101/152s,在该残差结构当中,主分支使用了三个卷积层,第一个是1x1的卷积层用来压缩channel维度,第二个是3x3的卷积层,第三个是1x1的卷积层用来还原channel维度(注意主分支上第一层卷积层和第二层卷积层所使用的卷积核个数是相同的,第三层是第一层的4倍)。该残差结构所对应的虚线残差结构如下图右侧所示,同样在捷径分支上有一层1x1的卷积层,它的卷积核个数与主分支上的第三层卷积层卷积核个数相同,注意每个卷积层的步距。

在这里插入图片描述

5. 迁移学习

迁移学习是一个比较大的领域,我们这里说的迁移学习是指神经网络训练中使用到的迁移学习。在迁移学习中,我们希望利用源任务(Source Task)学到的知识帮助学习目标任务 (Target Task)。例如,一个训练好的图像分类网络能够被用于另一个图像相关的任务。再比如,一个网络在仿真环境学习的知识可以被迁移到真实环境的网络。迁移学习一个典型的例子就是载入训练好VGG网络,这个大规模分类网络能将图像分到1000个类别,然后把这个网络用于另一个任务,如医学图像分类。

为什么可以这么做呢?如下图所示,神经网络逐层提取图像的深层信息,这样,预训练网络就相当于一个特征提取器。

在这里插入图片描述

使用迁移学习的优势:

  1. 能够快速的训练出一个理想的结果
  2. 当数据集较小时也能训练出理想的效果

   注意:使用别人预训练好的模型参数时,要注意别人的预处理方式。

常见的迁移学习方式:

  1. 载入权重后训练所有参数
  2. 载入权重后只训练最后几层参数
  3. 载入权重后在原网络基础上再添加一层全连接层,仅训练最后一个全连接层 

二、 Pytorch搭建ResNet

  • 定义ResNet18/34的残差结构,即BasicBlock
  • 定义ResNet50/101/152的残差结构,即Bottleneck
  • 定义ResNet网络结构
  • 定义resnet18/34/50/101/152

由于ResNet网络较深,直接训练的话会非常耗时,因此用迁移学习的方法导入预训练好的模型参数。其训练结果如下:该ResNet34的精度可达93.4%左右。

图像分类篇:pytorch实现ResNet_第3张图片

 预测结果:预测为郁金香的概率为1

图像分类篇:pytorch实现ResNet_第4张图片

参考博文:pytorch图像分类篇:6. ResNet网络结构详解与迁移学习简介

你可能感兴趣的:(pytorch,分类,深度学习)