CV05-ResNet笔记

news/2024/7/7 2:45:43

目录

一、为什么是ResNet

二、Residual Learning细节

2.1 shortcut计算

2.2 1×1卷积调整channel维度大小

2.3 ResNet层数

2.4 ResNet里的Basic Block 和 Bottleneck Block

2.5 Global Average Pooling 全局平均池化

2.6 Batch Normalization


学习ResNet,记录一些自己认为重要的要点,以免日后遗忘。

论文地址:https://arxiv.org/abs/1512.03385

论文下载请自备云梯。

复现论文代码:https://github.com/Ascetics/Pytorch-ResNet

一、为什么是ResNet

一般认为,当网络越来也深,其表现能力越强。但是,实际上网络的能力并不会随着深度增加一直增强,会出现网络的退化现象,也就是深度增加其能力反而不如浅层网络(其在测试集和训练集上的准确率都下降),这个不是过拟合(训练集上准确率提高,测试集上准确率下降)。

即使只增加恒等映射层,实验结果也是网络出现退化,随着深度的加深连学习一个恒等映射都变困难。所以,何恺明提出残差网络Residual Net,来解决这个问题。ResNet模型的出现使网络的深度大大增加。

论文3.1 Residual Learning中提出,如果要学习一个估值H(x)有困难,那么就定义残差F(x)=H(x)-x,学习残差F(x)相对容易,然后用H(x)=F(x)+x来学习到原来的估值H(x)

为什么残差可以解决退化的问题呢?我个人的理解就是,经过深度网络的卷积、激活函数,输入的信息损失太多。那么把这个损失的信息补回来就解决了退化问题。所以,每间隔几个卷积、激活函数就对结果加一次输入,这样就不会造成输入信息的损失,网络层数可以一直加下去。

二、Residual Learning细节

2.1 shortcut计算

Residual Net中的shortcut就是公式H(x)=F(x)+x中的输入x。如图,在经过卷积、ReLU、卷积以后,直接将输入加入,得到输出后再经过ReLU。这个Residual learning block计算并没有因为加入输入x而增加更多的参数。加入x是元素级别的加法,也就是说spatial和channel方向的维数要一致。

2.2 1×1卷积调整维度大小

因为卷积操作,导致channel发生了变化(stride=2导致spatial减小一倍,同时需要channel要增大一倍),所以需要对输入x做维度调整,才能做加法。

那么,1×1卷积就解决了channel不一致这个问题。至于spatial不一致,设置1×1卷积参数stride=2就可以解决。

2.3 ResNet层数

ResNet的层数指的是有参数的层数(卷积层、全连接层),也就是层数=conv1 + conv2 + conv3 + conv4 + conv5 + fc。根据层数的不同,ResNet分成5类,即ResNet18、ResNet34、ResNet50、ResNet101、ResNet152。

conv1是一个7×7卷积,out_channels=64,stride=2。经过这一层,out_channels变为64,spatial维数减小一半。

最大池化,kernel_size=3×3,stride=2。经过这一层,out_channels不变仍为64,输出spatial维数减小一半。

conv2-conv5根据层数不同使用不同数量的Basic Block或Bottleneck Block。

全局平均池化层,将张量拉成out_channels维度的向量,后面接全连接层。

将输出映射到n个分类,后面接softmax。

表格下面的文字描述,Downsampling is performed by conv3_1, conv4_1, and conv5_1 with stride of 2,容易被忽略。conv2是不做下采样的(stride=1)。conv3-conv5有多个block,但是只有第一个block才做下采样(stride=2),其余的不做下采样(stride=1)。

2.4 ResNet里的Basic Block 和 Bottleneck Block

随着深度的增加,每一层的参数个数会变的非常大(主要是channel变大,channel每层增大一倍,50层以上的ResNet的channel很大)。上面提到ResNet就是在计算得到的输出上加输入。为了提高效率,在层数较低的时(ResNet18、ResNet34 )使用Basic Block,在层数较高时(ResNet50、ResNet101、ResNet152)时使用Bottleneck Block。

第一种,在ResNet18、ResNet34使用Basic Block,每个Block都是两个维数相同的卷积,图中左侧省略了BN。输入和输出维度一致,计算输出直接加上输入就可以了。比如图中左侧,输入是channel=64,卷积计算和输出都是channel=64。需要注意,每个Basic Block的channel数不变,后一个conv层的channel是上一个conv层channel的2倍。

第二种,在ResNet50、ResNet101、ResNet152使用Bottleneck Block,每个Block的channel很大的情况,先用1×1卷积调整维度,将channel降下来进行卷积,再用1×1卷积将channel升上去,被称为BottleNeck。比如右图中,输入channel=256,先1×1卷积将channel降到64,计算输出是channel=64,再用1×1卷积将channel升到256,再做加法。256——64——256就像瓶颈一样——BottleNeck。需要注意,每个Bottleneck Block的channel输出都是输入的4倍,后一个conv层的输入channel是上一个conv层输出channel的2倍

 

2.5 Global Average Pooling 全局平均池化

为了连接全连接层。需要把矩阵拉成一维向量,以前办法是flatten。C×H×W的张量,经过flatten变成了一维向量,有CHW个元素。

而全局平均池化的意思,实际上就是池化的kernel_size和输入大小相同,这样每个channel就只有一个平均值输出。C×H×W的张量,经过全局平均池化变成了C×1×1,有C个元素。

全局平均池化的好处就是,全连接层的参数大大减少,避免过拟合。

2.6 Batch Normalization

ResNet统一的在卷积conv和激活函数ReLU之间使用BN,也就是说统一使用conv-BN-ReLU这样的顺序。

为什么卷积里面的bias=False?因为,后面有Batch Normalization。如果卷积就加bias,卷积后做batch normalization还要再加bias,那么卷积的bias就无效了。所以,后面如果有BN,卷积就不加bias。


http://lihuaxi.xjx100.cn/news/236020.html

相关文章

一点感悟和自勉

来学习linux,其实目的很简单,也很现实,就是为了学成之后找一份好的工作,能够养家糊口。 接触了几天,感觉挺难的,可能是因为我没有基础的原因吧,以前电脑只是用来打游戏和看电影,第一…

复杂度归纳--小结

一、复杂度分析的4个概念1.最坏情况时间复杂度:代码在最理想情况下执行的时间复杂度。2.最好情况时间复杂度:代码在最坏情况下执行的时间复杂度。3.平均时间复杂度:用代码在所有情况下执行的次数的加权平均值表示。4.均摊时间复杂度&#xff…

CV06-Xception笔记

目录 一、为啥是Xception 二、Xception结构 2.1 Xception结构基本描述 2.2 实现细节 2.3 DeepLabV3改进 三、记录pytorch采坑relu激活函数inplaceTrue Xception笔记,记录一些自己认为重要的要点,以免日后遗忘。 复现Xception论文、DeepLabV改进的…

聊聊flink的HistoryServer

为什么80%的码农都做不了架构师?>>> 序 本文主要研究一下flink的HistoryServer HistoryServer flink-1.7.2/flink-runtime-web/src/main/java/org/apache/flink/runtime/webmonitor/history/HistoryServer.java public class HistoryServer {private st…

WPF的消息机制(二)- WPF内部的5个窗口之隐藏消息窗口

原文:WPF的消息机制(二)- WPF内部的5个窗口之隐藏消息窗口版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/powertoolsteam/article/details/6109036 目录 WPF的消息机制(一)-让…

【转载】Pytorch在加载模型参数时指定设备

转载 https://sparkydogx.github.io/2018/09/26/pytorch-state-dict-gpu-to-cpu/ >>> torch.load(tensors.pt) # Load all tensors onto the CPU >>> torch.load(tensors.pt, map_locationtorch.device(cpu)) # Load all tensors onto the CPU, using a fun…

20189317 《网络攻防技术》 第二周作业

一.黑客信息 (1)国外黑客 1971年,卡普尔从耶鲁大学毕业。在校期间,他专修心理学、语言学以及计算机学科。也就是在这时他开始对计算机萌生兴趣。他继续到研究生院深造。20世纪60年代,退学是许多人的一个选择。只靠知识…

为什么 JavaScript 的私有属性使用 # 符号

这几天 JavaScript 的私有属性又成为了前端社区热议的话题。原因很简单,这家伙长这样: 惊不惊喜!意不意外! 而且 TC39 委员会以及对此达成了一致意见,并且该提案已经进入了 stage 3。在 es 规范阶段 stage 3 是候选提案…