【论文解读】CNN深度卷积神经网络-ResNet

24.jpg

1.简介

深度残差网络(deep residual network)是2015年微软何凯明团队发表的一篇名为:《Deep Residual Learning for Image Recognition》的论文中提出的一种全新的网络结构,其核心模块是残差块residual block。正是由于残差块结构的出现使得深度神经网络模型的层数可以不断加深到100层、1000层甚至更深,从而使得该团队在当年的ILSVRC 2015分类竞赛中取得卓越成绩,也深刻地影响了以后的很多深度神经网络的结构设计。
残差网络的成功不仅表现在其在ILSVRC 2015竞赛中的卓越效果,更是因为残差块skip connection/shorcut这样优秀的思想和设计,使得卷积网络随着层数加深而导致的模型退化问题能被够大幅解决,使模型深度提高一个数量级,到达上百、上千层。

1.1网络加深的后果

在残差块这样的结构引入之前,如果一个神经网络模型的深度太深,可能会带来梯度消失和梯度爆炸的问题(如下图),随着一些正则化方法的应用可以缓解此问题,但是随着layer深度的继续加深,又带来了模型退化这样的问题。而添加了带shortcut的残差块结构之后,使得整个深度神经网络的层数可以大幅增加,变得更【深】,从而有时会带来更好的训练效果。

1.2 网络模型的退化

下图为CIFER10在20层和56层普通网络结构下测试和训练过程中的损失。可见,仅仅简单地加深网络,并没有带来精度的提升,相反会导致网络模型的退化。
image.png

那么,这里就有一个问题,为什么加深网络会带来退化问题?即使新增的这些layer什么都没学习,保持恒等输出(所有的weight都设为1),那么按理说网络的精度也应该 = 原有未加深时的水平,如果新增的layer学习到了有用特征,那么必然加深过后的模型精度会 > 未加深的原网络。看起来对于网络的精度加深后都应该 >= 加深前才对啊 ?
实际上,让新增的layer保持什么都不学习的恒等状态,恰恰很困难,因为在训练过程中每一层layer都通过线性修正单元relu处理,而这样的处理方式必然带来特征的信息损失(不论是有效特征or冗余特征)。所以上述假设的前提是不成立的,简单的堆叠layer必然会带来退化问题。

1.3 退化问题的解决

到此,何凯明团队创新地提出了残差块的构想,通过shortcut/skip connection这样的方式(最初出现在highway network中),绕过这些新增的layer,既然保持新增layer的identity恒等性很困难,那就直接绕过它们,通过shortcut通路来保持恒等。如图2所示:

figure-2.png
figure-2.png
这里假设原有网络结构的基础映射为H(x),这里又添加了两个layer,在网络中的映射称为F(x)。既然新增layer保持不了恒等性,那我们可以通过skip connection/shortcut来直接跳过它们,在shortcut上保持恒等,为了保持新结构的输出F(x) + x = H(x)同原输出H(x)相近,这里我只需要优化F(x),使其趋于0即可,而使得F(x)接近0是相对比较容易的(无论是从权重初始化的角度还是激活函数特征过滤的角度)
到这里,算是【曲线救国】了,虽然新增的F(x)不容易保持恒等,但让其尽量靠近0,还是相对容易做到的,这种训练方式称为残差学习,这种结构块也称为Residual Block残差块。正是残差结构的出现,使得残差网络能很好的加深网络层数,同时解决退化问题。

1.4 资源下载

【2015】【ResNet】1512.03385v1.pdf
训练代码(官方实现):https://github.com/facebookarchive/fb.resnet.torch

2.Abstract

Abstract
Deeper neural networks are more difficult to train. We present a residual learning framework to ease the training of networks that are substantially deeper than those used previously. We explicitly reformulate the layers as learning residual functions with reference to the layer inputs, instead of learning unreferenced functions. We provide comprehensive empirical evidence showing that these residual networks are easier to optimize, and can gain accuracy from considerably increased depth. On the ImageNet dataset we evaluate residual nets with a depth of up to 152 layers—8×deeper than VGG nets [41] but still having lower complexity. An ensemble of these residual nets achieves 3.57% erroron the ImageNet testset. This result won the 1st place on theILSVRC 2015 classification task. We also present analysison CIFAR-10 with 100 and 1000 layers.
The depth of representations is of central importancefor many visual recognition tasks. Solely due to our extremely deep representations, we obtain a 28% relative improvement on the COCO object detection dataset. Deepresidual nets are foundations of our submissions to ILSVRC& COCO 2015 competitions1, where we also won the 1stplaces on the tasks of ImageNet detection, ImageNet localization, COCO detection, and COCO segmentation
翻译
更深的神经网络更难训练。 我们提出了一种残差的学习框架,以简化比之前使用的网络还要深入的网络结构的训练。 我们通过改变一些层的输入来调整了这些层的结构以构造成残差函数来进行学习。我们提供了全面的经验证据,表明这些残差网络更易于优化,并且可以通过深度的增加而提升准确性。 在ImageNet数据集上,我们评估深度最大为152层的残差网络-比VGG网络[41]深8倍,但复杂度仍然较低。 这些残差网络整体在ImageNet测试集上实现了3.57%的误差。 该结果在ILSVRC 2015分类任务中获得第一名。 我们还将介绍具有100和1000层的基于CIFAR-10的分析。
表征深度对于许多视觉识别任务至关重要。 仅由于我们更深的网络结构,我们在COCO对象检测数据集上获得了28%的相对改进。 深度残差网络是我们提交ILSVRC&COCO 2015竞赛夺冠的基础,在该竞赛中,我们还获得了ImageNet检测,ImageNet本地化,COCO检测和COCO分割等任务的第一名

3.网络结构

3.1 示意图

image.png

3.2 残差块

figure-2.png
figure-2.png
figure-5.png
figure-5.png
figure-5.png
figure-5.png

4.论文解读

1.介绍

论文中Introduction部分的内容及思想,主要内容为残差学习和残差块提出的原因,解决的问题,在竞赛中取得的佳绩等。(以下大多数内容和1.简介中的类似)
深度神经网络模型随着深度加深,精度和表现都会提高。但是随着深度逐渐加深也会带来其他问题,首当其冲的是梯度消失和梯度爆炸,但是随着标准初始化和中间的正则化层解决了此问题,使得数十层的网络可以在随机梯度下降SGD过程中进行反向传播和收敛。然而,随着网络深度的进一步加深,模型的准确性达到饱和然后迅速下降,而且这种退化并不是由于过拟合所导致。如图所示:

Figure1:CIFER10在20层和56层普通网络结构下测试和训练过程中的损失对比.png
训练准确性的下降表明,并非所有系统都同样易于优化。 让我们考虑一下一个较浅的网络结构,以及它的更深层次的对应结构。 有一个通过构造更深层模型的解决方案:添加的层是恒等映射,其他层是从学习的较浅层模型中复制的。 该构造方案的存在表明,更深的模型应该不会比其较浅的模型产生更高的训练误差,但是实验表明,我们现有的求解器无法找到与构造的解决方案相比更好或更好的解决方案(或无法做到) 在可行的时间内)

在本文中,我们通过引入深度残差学习框架解决降级问题,而不是希望每个堆叠的层都直接适合所需的基础映射,而是明确让这些层适合残差映射。 形式上,将所需的基础映射表示为H(x),我们让堆叠的非线性层(图中的weight layer)适合F(x) := H(x) - x的另一个映射。 原始映射将重铸为F(x) + x。 我们假设与优化原始,未引用的映射相比,更容易优化残留映射。 极端地,如果identity特征映射是最佳的,则将残差推为零比通过用一叠非线性层拟合特征映射要容易。

图2.png
图2.png
F(x)+ x的表示可以通过具有“shortcut跳远连接”的前馈神经网络来实现(图2)。shortcut[2、34、49]是跳过一层或多层的连接。 在我们的情况下,shortcut连接仅执行恒等映射,并将它们的输出添加到堆叠层的输出中(图2)。 shortcut的连接方式既不会增加额外的参数,也不会增加计算复杂性。 整个网络仍然可以通过SGD反向传播进行端到端训练,并且可以使用通用库(例如Caffe [19])轻松实现,而无需修改求解器。


针对上述构想,作者团队在ImageNet上做了全面实验并证明:

  • 1.随着网络层数的增加,普通网络结构的训练误差相比残差网络更高
  • 2.深度残差网络可以更容易地通过增加深度来提高网络精度,而且结果比浅层网络好很多。

作者团队在在CIFAR-10数据集成功训练了深度超过100层以上的模型,也得到了同样的结论。并实验了1000层以上模型的训练。在ImageNet的分类数据集上,残差网络在测试集上取得了3.57%的top-5错误率从而获得ILSVRC2015分类挑战赛的冠军,同时152层的网络深度刷新了记录且其参数量比VGGNet还少。
除此之外,通过极深的残差网络,其团队在ILSVRC和COCO 2015中的各项细分比赛中都获得了冠军,如:ImageNet目标检测、定位;COCO目标检测、分割。这些证据表明残差学习的原则是通用的,在多项任务中都有着出色的泛化能力。

2.相关工作

残差表示

主要内容是从图像检索和分类的角度,残差矢量计算的对比和优化,从理论上给出证据表面残差方案使得训练时的模型收敛速度加快。以下是原论文翻译:

在图像识别中,VLAD [18]是通过相对于字典的残差矢量进行编码的表示,Fisher Vector [30]可以表示为VLAD的概率版本[18]。 它们都是用于图像检索和分类的有效的浅层表示[4,48]。 对于向量量化,编码残差向量[17]比编码原始向量更有效。在低级视觉和计算机图形学中,为求解偏微分方程(PDE),广泛使用的Multigrid方法[3]将系统引申出多个规模的子问题,其中每个子问题负责在较粗和较精scale之间的残差解决方案。 Multigrid的替代方法是以分层为基础的预处理[45,46],它依赖于代表两种scale之间的残差向量的变量。 已经证明[3、45、46],这些方案的收敛速度比那些对残差本质尚未涉及的标准方案快得多。 这些方法表明,良好的重构或预处理可以简化优化过程。

shortcut连接

这一小节主要是进行了shortcut理论和实践的溯源,还有同highway network中shortcut功能区别的对比。以下部分是原论文翻译:

关于shortcut连接的实践和理论[2,34,49]已有很长时间的研究。 训练多层感知器(MLP)的早期实践是添加从网络输入连接到输出的线性层(如:Pattern recognition and neural networks. Cambridgeuniversity press, 1996)。 在GoogLeNet等网络中,一些中间层直接连接到辅助分类器,以解决消失/爆炸梯度。 文献[39,38,31,47]提出了通过shortcut连接实现对层响应,梯度和传播误差进行居中的方法。 在GoogLeNet中,“Inception”层由shortcut分支和一些更深的分支组成。
与我们同期的工作,“highway networks” [42、43]中,shortcut连接作为门功能[15]而呈现。这些门(gates)是带参的且依赖数据的,正与我们shortcut带参且有恒等性相反。当shortcut门“关闭”时(接近0),highway networks中的层表现出非残差功能;相反我们的表达式却永远在进行残差的学习。我们的shortcut永远不会关闭,所有信息始终通过其传递,同时残差函数也始终在进行学习。此外,highway networks并没有证明,随着深度增加,准确性有了明显提升。

3.深度残差学习

3.2 shortcut恒等映射

在残差网络中,对每一个堆叠层都采用残差学习,一个堆叠层形如图2所示的一个残差块。

figure-2.png
figure-2.png
残差块的公式定义为:
这里x和y分别为输入输出;即代表需要进行残差学习的函数。以图2展示的残差块为例,残差函数可以表示为:(激活函数为ReLU,且省略了bias)作者指出,这个公式并没有引入额外参数,也没有增加计算复杂度。

x和F(x)计算时尺寸必须相等,为此我们可以在必要时通过矩阵Ws来改变输入x的维度:\mathbf{y}=\mathcal{F}\left(\mathbf{x},\left\{W_{i}\right\}\right)+W_{s} \mathbf{x}在残差块中堆叠的layer数量至少为2,因为如果只增加了1层,整个表达式便退化成了线性方程,而这就失去作用了。为了简单起见,表达式看上去只适合全连接层,其实可也以表示卷积层,F(x,{Wi})可以表示多个卷积层。在两个feature maps之间,元素之间的相加是在通道维上逐个进行的。

3.3 网络结构

作者及其团队已经测试过各种普通/残差网络,并观测到一致的现象,这里仅举ImageNet中的两个模型作为说明。
image.png

普通网络

上图中间的是34层的基准普通网络,包含34个带权层(conv+fc)。其设计参考了VGG-19,卷积层的filter尺寸多为3×3,并遵循两个设计原则:1.如果输出的特征图尺寸减半,则filter数量加倍 2.如果输出的特征图尺寸不变,filter数量也不变。stride保持为2,网络结束之前会经过全局平均池化层,再连接一个1000路的softmax分类。

论文指出残差网络比VGG网络有着更少的过滤器和更低的复杂度,34层的基准网络有36亿个FLOP(乘加),而VGG-19有196亿个FLOP,仅占其18%。

残差网络

上图最右边是在中间普通网络基础上,增加了shortcut,使其变为了残差网络。这里有两种shortcut,实线shortcut和虚线shortcut(投影projection)。当输入和输出维度相同时,使用实线shortcut,当维度增加时使用虚线shortcut。当维度改变使用虚线shortcut时,我们为了匹配维度有2种做法:

  • (A) shortcut任执行恒等映射,增加额外的0项来增加维度
  • (B)使用等式\mathbf{y}=\mathcal{F}\left(\mathbf{x},\left\{W_{i}\right\}\right)+W_{s} \mathbf{x} 中的方式,通过1×1卷积来改变维度

3.4 实现

对ImageNet的残差网络实现参照了VGGNet及其在ImageNet中的实现。
图像resize,并水平翻转,随机剪裁减去RGB均值像素,颜色增强等处理;
BN批量正则化;
batch size设为256;
随机梯度下降SGD;
初始学习率为0.1当loss稳定后除以10;
weight decay设为0.0001;
动量0.9;
值得注意的是,在该实现中并没有使用Dropout方法。

4.实验

4.1 ImageNet分类

作者在ImageNet2012分类数据集评估了残差网络,128万张训练图,5万张验证图,1000个分类,在测试服务器上通过10万张测试图评估得到了top-1和top-5错误率。

figure-4.png
table-2.png

普通网络

上图左边可看出,在普通网络的对比中,34层的比18层误差大,存在模型退化现象。

残差网络

通过对比左右两幅图+table2可以发现:当模型深度不是很深时(18)层,普通网络和ResNet网络的准确率差不多,表示通过一些初始化和正则化方法,可以降低普通卷积神经网络的过拟合;但当层数不断加深,就不可避免地出现模型退化现象,而此时ResNet可以在此情况下很好地解决退化问题。

作者团队不仅实验了34层的ResNet更实验了多种残差块,多种深度的残差网络,结构如下:

table-1.png

其中,以50层layer中的残差块为例,由于其输入输出尺寸不同,需要1×1卷积进行维度转换,这种残差block表现出上窄下宽的形状,被称为“瓶颈”残差块。具体如下图:

figure-5.png

不同深度ResNet的对比

table-3.png

可以看见,在ResNet网络中,并没有看到模型退化的现象,反而随着layer深度加深,网络的精度越高。

各种经典网络对比

table-5.png

5.代码实现

这里使用tensorflow2.0实现ResNet-18网络结构,完整训练可参考:残差网络(ResNet)。我们先看一下ResNet-18的网络结构:

选区_075.png

ResNet的前两层跟之前介绍的GoogLeNet中的一样:在输出通道数为64、步幅为2的7×7卷积层后接步幅为2的3×3的最大池化层。不同之处在于ResNet每个卷积层后增加的批量归一化层。然后接了4种类型的共计8个残差块,每种类型的2个残差块形成一个堆叠。最后加了全局平均池化和1000路的softmax输出。

5.1定义残差块

残差块沿用了VGG的3×3的卷积核尺寸,且有两种结构:初入 = 输出;输入!=输出。针对输入和输出shape不一样的情况,需要增加一个1×1卷积变换维度。残差块内的卷积层经过卷积后接BN批量归一化层,然后经过ReLU激活。

定义残差块实现类Residual:

import tensorflow as tf
from tensorflow.keras import layers,activations
class Residual(tf.keras.Model):
    def __init__(self, num_channels, use_1x1conv=False, strides=1, **kwargs):
        super(Residual, self).__init__(**kwargs)
        self.conv1 = layers.Conv2D(num_channels,
                                   padding='same',
                                   kernel_size=3,
                                   strides=strides)
        self.conv2 = layers.Conv2D(num_channels, kernel_size=3,padding='same')
        # 如果需要变换维度,则增加1×1卷积层
        if use_1x1conv:
            self.conv3 = layers.Conv2D(num_channels,
                                       kernel_size=1,
                                       strides=strides)
        else:
            self.conv3 = None
        self.bn1 = layers.BatchNormalization()
        self.bn2 = layers.BatchNormalization()

    def call(self, X):
        Y = activations.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        return activations.relu(Y + X)

5.2定义残差块stack

ResNet-18总计4个残差块stack,每个stack包含两个残差块。下面定义残差块stack

class ResnetBlock(tf.keras.layers.Layer):
    def __init__(self,num_channels, num_residuals, first_block=False,**kwargs):
        super(ResnetBlock, self).__init__(**kwargs)
        self.listLayers=[]
        for i in range(num_residuals):
            if i == 0 and not first_block:
                self.listLayers.append(Residual(num_channels, use_1x1conv=True, strides=2))
            else:
                self.listLayers.append(Residual(num_channels))      

    def call(self, X):
        for layer in self.listLayers.layers:
            X = layer(X)
        return X

5.3定义ResNet

class ResNet(tf.keras.Model):
    def __init__(self,num_blocks,**kwargs):
        super(ResNet, self).__init__(**kwargs)
        self.conv=layers.Conv2D(64, kernel_size=7, strides=2, padding='same')
        self.bn=layers.BatchNormalization()
        self.relu=layers.Activation('relu')
        self.mp=layers.MaxPool2D(pool_size=3, strides=2, padding='same')
        self.resnet_block1=ResnetBlock(64,num_blocks[0], first_block=True)
        self.resnet_block2=ResnetBlock(128,num_blocks[1])
        self.resnet_block3=ResnetBlock(256,num_blocks[2])
        self.resnet_block4=ResnetBlock(512,num_blocks[3])
        self.gap=layers.GlobalAvgPool2D()
        self.fc=layers.Dense(units=1000,activation=tf.keras.activations.softmax)

    def call(self, x):
        x=self.conv(x)
        x=self.bn(x)
        x=self.relu(x)
        x=self.mp(x)
        x=self.resnet_block1(x)
        x=self.resnet_block2(x)
        x=self.resnet_block3(x)
        x=self.resnet_block4(x)
        x=self.gap(x)
        x=self.fc(x)
        return x

mynet=ResNet([2,2,2,2])

# 观察ResNet网络的输出
X = tf.random.uniform(shape=(1,  224, 224 , 3))
for layer in mynet.layers:
    X = layer(X)
    print(layer.name, 'output shape:\t', X.shape)

输出:

conv2d output shape:  (1, 112, 112, 64)
batch_normalization output shape:  (1, 112, 112, 64)
activation output shape:  (1, 112, 112, 64)
max_pooling2d output shape:  (1, 56, 56, 64)
resnet_block output shape:  (1, 56, 56, 64)
resnet_block_1 output shape:  (1, 28, 28, 128)
resnet_block_2 output shape:  (1, 14, 14, 256)
resnet_block_3 output shape:  (1, 7, 7, 512)
global_average_pooling2d output shape:  (1, 512)
dense output shape:  (1, 1000)

6.总结

残差网络的出现使人们摆脱了【深度】的束缚,大幅改善了深度神经网络中的模型退化问题,使网络层数从数十层跃升至几百上千层,大幅提高了模型精度,通用性强适合各种类型的数据集和任务。残差块和shortcut这种优秀的设计也极大影响了后面的网络结构发展。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容