1 为什么会有ResNet?

自从深度神经网络在ImageNet大放异彩之后,后来问世的深度神经网络就朝着网络层数越来越深的方向发展。直觉上我们不难得出结论:增加网络深度后,网络可以进行更加复杂的特征提取,因此更深的模型可以取得更好的结果。

但事实并非如此,人们发现随着网络深度的增加,模型精度并不总是提升,并且这个问题显然不是由过拟合(overfitting)造成的,因为网络加深后不仅测试误差变高了,它的训练误差竟然也变高了。【注:过拟合应该是训练误差很小,但是测试误差很大;这里训练误差都很大,说明不是过拟合的问题】

这可能是因为更深的网络会伴随梯度消失/爆炸问题,从而阻碍网络的收敛。这种加深网络深度但网络性能却下降的现象被称为退化问题(degradation problem)。

从上图我们可以看出,当传统神经网络的层数从20增加为56时,网络的训练误差和测试误差均出现了明显的增长,也就是说,网络的性能随着深度的增加出现了明显的退化。

   ResNet就是为了解决这种退化问题而诞生的。

2 ResNet原理

随着网络层数的增加,梯度爆炸和梯度消失问题严重制约了神经网络的性能,研究人员通过提出包括Batch normalization在内的方法,已经在一定程度上缓解了这个问题,但依然不足以满足需求。

2.1 恒等映射(Identity mapping)

ResNet提出了使用恒等映射(Identity mapping)来解决这个问题。

问题解决的标志是:增加网络层数,但训练误差不增加。

那怎么构建恒等映射呢?

简单地说,原先的网络输入x,希望输出H(x)。

现在我们改一改,我们令H(x)=F(x)+x,那么我们的网络就只需要学习输出一个残差F(x)=H(x)-x。

ResNet作者提出,学习残差F(x)=H(x)-x会比直接学习原始特征H(x)简单的多。

2.2 skip connection

3 ResNet(各变体)网络结构

ResNet有很多变体,比较著名的有五种主要形式:Res18,Res34,Res50,Res101,Res152。

如上图所示,ResNet及其变体主要包括三个主要部分:输入部分(input)+中间卷积(stage1~stage4)+输出部分(output)

3.1 网络整体结构

以ResNet18为例:

class ResNet(nn.Module):def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)#输入部分x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)#卷积部分#ResNet18和其他的ResNet网络的区别主要就在这四层里面x = self.avgpool(x)x = x.view(x.size(0), -1)x = self.fc(x)#输出部分return x# 生成一个res18网络(看是否有预训练的参数)
def resnet18(pretrained=False, **kwargs):model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)if pretrained:model.load_state_dict(model_zoo.load_url(model_urls['resnet18']))return model

3.2 网络输入部分

        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
'''
size=7*7,stride=2的卷积核
'''self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1
'''
size=3x3, stride=2的最大池化
''')

在pytorch 笔记:torch.nn.Conv2d_UQI-LIUWJ的博客-CSDN博客、pytorch笔记:torch.nn.MaxPool2d_UQI-LIUWJ的博客-CSDN博客中,我们说到,经过Conv2d和MaxPool2d之后的channel数为:

在ResNet中,输入部分是一个224x224的图像,经过输入部分之后,变成了56x56大小的特征图,极大减少了存储所需大小。

3.3 中间卷积部分

中间卷积部分主要是下图中的蓝框部分,通过3*3卷积的堆叠来实现信息的提取。红框中的[2, 2, 2, 2]和[3, 4, 6, 3]等则代表了bolck的重复堆叠次数。

——>每一层卷积层:减一半feature map的长和宽,增加输出channel一倍

——>第一个卷积层(conv1——,又被称为”stem“)

红框前面的是卷积核的大小,以及输出的channel数

刚刚我们调用的resnet18( )函数中有一句

model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)

这里的[2, 2, 2, 2]与图中红框是一致的,如果你将这行代码改为 ResNet(BasicBlock, [3, 4, 6, 3], **kwargs), 那你就会得到一个res34网络。

3.4  残差块

下面我们来具体看一下一个残差块是怎么实现的。

如下图所示的basic-block,输入数据分成两条路,一条路经过两个3*3卷积,另一条路直接短接,二者相加经过relu输出,十分简单。

class BasicBlock(nn.Module):expansion = 1def __init__(self, inplanes, planes, stride=1, downsample=None):super(BasicBlock, self).__init__()self.conv1 = conv3x3(inplanes, planes, stride)self.bn1 = nn.BatchNorm2d(planes)self.relu = nn.ReLU(inplace=True)self.conv2 = conv3x3(planes, planes)self.bn2 = nn.BatchNorm2d(planes)self.downsample = downsampleself.stride = stridedef forward(self, x):identity = xout = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)if self.downsample is not None:identity = self.downsample(x)out += identityout = self.relu(out)return out

3.5 输出部分

网络输出部分很简单,通过全局自适应平滑池化,把所有的特征图拉成1*1。

对于res18来说,就是1x512x7x7 的输入数据拉成 1x512x1x1,然后接全连接层输出,输出节点个数与预测类别个数一致。

        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(512 * block.expansion, num_classes)

4 bottleneck 结构

ResNet50起,就采用Bottleneck结构,主要是引入1x1卷积。

我们来看一下这里的1x1卷积有什么作用:

  • 对通道数进行升维和降维(跨通道信息整合),实现了多个特征图的线性组合,同时保持了原有的特征图大小;
  • 相比于其他尺寸的卷积核,可以极大地降低运算复杂度;
  • 如果使用两个3x3卷积堆叠,只有一个relu,但使用1x1卷积就会有两个relu,引入了更多的非线性映射;

我们来计算一下1*1卷积的计算量优势:首先看上图右边的bottleneck结构,对于256维的输入特征,参数数目:1x1x256x64+3x3x64x64+1x1x64x256=69632.

如果同样的输入输出维度但不使用1x1卷积,而使用两个3x3卷积的话,参数数目为(3x3x256x256)x2=1179648。

简单计算下就知道了,使用了1x1卷积的bottleneck将计算量简化为原有的5.9%,收益超高。

参考文献:ResNet及其变种的结构梳理、有效性分析与代码解读 - 知乎 (zhihu.com)

5 Batch-normalization和Relu,孰先孰后?

这个不确定,这里说一下ResNet中先BN再Relu的优点吧

先BN的话,会有一半左右的输出小于0,那么经过Relu之后的结果就是0,网络可以剪掉很多枝

机器学习笔记:ResNet 及残差连接相关推荐

  1. 「模型解读」resnet中的残差连接,你确定真的看懂了?

    https://www.toutiao.com/a6708715626782786061/ 1 残差连接 想必做深度学习的都知道skip connect,也就是残差连接,那什么是skip connec ...

  2. 【模型解读】resnet中的残差连接,你确定真的看懂了?

    文章首发于微信公众号<与有三学AI> [模型解读]resnet中的残差连接,你确定真的看懂了? 这是深度学习模型解读第6篇,本篇我们将介绍深度学习模型中的残差连接. 作者&编辑 | ...

  3. 关于Resnet网络中残差连接实线与虚线的含义

    何凯明大神的残差网络在论文中给出了两种连接,分别是实线连接和虚线连接 那么图中的实线和虚线分别是什么含义呢? 在图中可以看到,每两层是作为一个block存在的,两层之间用实线或者虚线链接,实线连接的部 ...

  4. 机器学习笔记:Transformer

    1 传统Seq2Seq的不足 传统seq2seq 使用 bi-direction RNN,那么生成每个b的时候,对于输入的整个序列,模型都需要看过一遍. 问题在于,这样的用bi-direction R ...

  5. 机器学习笔记 - YOLO家族简介

    一.背景概述 目标检测是计算机视觉中最重要的课题之一.大多数计算机视觉问题都涉及检测视觉对象类别,如行人.汽车.公共汽车.人脸等.这一领域不仅限于学术界,而且在视频监控.医疗保健.车载传感和自动驾驶. ...

  6. Mechine Learning 机器学习笔记

    笔记作者:OUC_Shizue 参考课程:复旦大学 邱锡鹏 <神经网络与深度学习> 第一章:机器学习概论 一.机器学习的定义 1.直接定义 ​ 机器学习≈计算机自动构建映射函数 ​ Mac ...

  7. ResNet之残差结构的理解

    ResNet 论文 2015年提出的ResNet 2016年改进后的ResNet 博客 本人实现的2015-2016的ResNet网络复现 深度学习-残差resnet网络原理详解 ResNet详解-- ...

  8. 【学习打卡03】可解释机器学习笔记之CAM类激活热力图

    可解释机器学习笔记之CAM类激活热力图 文章目录 可解释机器学习笔记之CAM类激活热力图 CAM介绍 CAM算法原理 GAP全局平均池化 GAP VS GMP CAM算法的缺点及改进 CAM可视化 同 ...

  9. ResNet、残差结构、迁移学习

    文章目录 前言 一.ResNet 二.残差结构 BN层 三.迁移学习 前言 机器学习基本知识--Resnet.残差结构.迁移学习 参考内容来自b站up主:https://space.bilibili. ...

最新文章

  1. LeetCode 26 号问题 删除数组中的重复项
  2. (转载)linux下的find文件查找命令与grep文件内容查找命令
  3. 查看 php-cgi 进程数
  4. Device Tree(三):代码分析【转】
  5. chapter3.1封装和解构
  6. file相对路径java_浅谈java 中文件的读取File、以及相对路径的问题
  7. python-基础-代码备注与变量命名方法
  8. 加个ing是什么意思_英语中动词ed和ing形式作形容词时用法有啥区别,牢记以下要点!...
  9. stats | 线性回归(四)——显著性检验和模型评价
  10. 谷歌浏览器开发者工具解析
  11. Logstash实践: 分布式系统的日志监控
  12. ffmpeg (三):ffmpeg结合SDL2.0解码音频流
  13. 如何使用postman带Token测试接口?
  14. JavaScript 系列笔记(一)数据类型
  15. LightGBM算法解析
  16. excel如何冻结表格行或者列
  17. 湖南大学14届新生赛--B--bearBabylovessleeping
  18. starbound服务器配置文件怎么写,【mod向】简单修改文件迅速刷到任何想要物品以及修改随机生成物品入手时数据可以带入任何服务器【修改向】...
  19. java测试复盘2(2019.8.21)
  20. 存储系统 - IOPS与带宽的关系

热门文章

  1. progress与meter的区别
  2. 洛谷P1202 [USACO1.1]黑色星期五Friday the Thirteenth
  3. Composer 中国全量镜像(二)
  4. php学习笔记之static的问题
  5. 《20年后,你靠什么生存(孙继滨)》讲座观后感
  6. WIFI 一键配置原理-ESP8266
  7. 高精度乘以低精度板子
  8. php程序监控指标,通达信主力动向监控副图指标公式
  9. 参数命名_北汽极狐ARCFOX 旗下首款车参数曝光,或命名MARK5
  10. batchsize设置为2的n次方_试卷中的页码设置