ResNet详解:你尽管堆层,我来担责

ResNet详解:你尽管堆层,我来担责
abinng😶🌫️author: abinng date: 2025-12-24 15:57
createDate:2025-12-24 15:57
本篇推荐几个知乎链接: Resnet到底在解决一个什么问题呢? - 知乎 Resnet中残差块的作用是完成恒等变换,那这样的恒等变换的意义是什么,在网络中能起到怎样的作用呢? - 知乎
背景
残差神经网络(ResNet)是由微软研究院的何恺明、张祥雨、任少卿、孙剑等人提出的。ResNet 在2015 年的ILSVRC(ImageNet Large Scale Visual Recognition Challenge)中取得了冠军。
残差神经网络的主要贡献是发现了网络加深会出现的“退化现象(Degradation)”,并针对退化现象发明了 “快捷连接(Shortcut connection)”,极大的消除了深度过大的神经网络训练困难问题。神经网络的“深度”首次突破了100层、最大的神经网络甚至超过了1000层。
引入
在2012年的ILSVRC挑战赛中,
它是正确的,至少在理论上是正确的。
假设一个层数较少的神经网络已经达到了较高准确率,我们可以在这个神经网络之后,拼接一段恒等变换的网络层,这些恒等变换的网络层对输入数据不做任何转换,直接返回(y=x),就能得到一个深度较大的神经网络,并且,这个深度较大的神经网络的准确率等于拼接之前的神经网络准确率,准确率没有理由降低。
上述层数较多的神经网络,可由较浅的神经网络和恒等变换网络拼接而成,如下图所示。
(这里恒等变换是指经过该网络层之后信息没有任何损失,即该网络层几乎仅仅是为了加深深度用的)
网络加深带来哪些问题
首先带来的就是梯度消失/梯度爆炸,而一些正则化方法(如Dropout)的应用可以缓解此问题。但是随着层深度继续加深,又带来了模型退化这样的问题,非常反直觉,在此之前都是网络层越深,模型效果越好的……
为什么会模型退化?还是用上面的例子,准确率较高的层数较少的神经网络拼上了
即使新增的这些layer什么都没学习,保持恒等输出(所有的weight都设为1),那么按理说网络的精度也应该等于原有未加深时的水平(这就是上面所说的恒等变换层)
如果新增的layer学习到了有用特征,那么必然加深过后的模型精度会大于未加深的原网络。看起来对于网络的精度加深后都应该大于等于加深前才对啊?
实际上,让新增的layer保持什么都不学习的恒等状态,恰恰很困难,因为在训练过程中每一层layer都通过线性修正单元relu处理,而这样的处理方式必然带来特征的信息损失(不论是有效特征or冗余特征)。所以上述假设的前提是不成立的,简单的堆叠layer必然会带来退化问题。
信息丢失
- 原理:在标准的前馈网络中,信息经过一层层的非线性变换(如ReLU、Sigmoid、池化等),原始输入的信息可能会被逐渐“洗掉”或不可逆地破坏。
- 后果:当网络太深时,最后几层可能已经丢失了输入图片中关键的细节信息,导致无法做出正确的分类或预测。 原因之一:陷入局部极小值,学习停滞,深度网络很容易出现这种现象
残差块

通俗来讲,一般卷积块的输出是
所以,ResNet 确实赋予了网络“如果这一层没用,就把它关掉(变成恒等变换)”的能力。 就像上面引入中拼的神经网络一样。
残差块的架构
ResNet的残差块的结构也有一个“+“的地方,回想GoogLeNet的Inception块,好像也有一个”+“,但是这两个有不同之处:
先简述一下Inception块:他的“+“的部分叫通道合并,举例来说就是
而ResNet这里的“+“是指:
也就是说ResNet的这个操作对通道数还有要求,所以我们可以用
Batch Normalization(批量规范化)
前面学AlexNet的时候说LRN(局部归一化)后面没有被广泛应用,因为它确实没什么提升,并且后面BN出来之后,就几乎没人用了,这里的BN就是说的Batch Normalization
为什么需要归一化
- 优化器收敛速度与稳定性 梯度下降过程中,如果特征尺度差异大,那么就更容易往最陡峭的坡度下降,坡度不均匀,会在长轴上缓慢前景,而在短轴方向上来回震荡(“Z字形”路径),导致收敛速度非常慢,甚至可能在训练过程中发散,很难找到最优解。 归一化后,所有特征的尺度都变得相似(例如,都缩放到0到1之间,或均值为0、方差为1),损失函数的形状会更接近一个圆形的碗。这样,梯度下降可以更直接、更稳定地朝着最小值前进,大大加快收敛速度,并提高训练的稳定性。
- 权重初始化与特征影响力不对等
一张图像中,由于物理量等原因,有的特征可能参数比较大,有的特征可能参数比较小,举一个不恰当的例子:可能眼睛部分以直径为参数,是
;但是背景部分以面积为参数,是 ,这样就导致数字大小不同,而神经网络中是不看单位的,所以数字大小就直接拿去计算,神经网络并不知道 代表眼睛(重要特征), 代表背景(次要特征)。这时候我们的初始化权重不起作用,因为即使是相同的初始化权重,数值大的特征对最终输出和损失函数的影响也会远大于数值小的特征。 归一化后就可以使得所有特征在输入时具有相似的数值范围,确保每个特征在训练初期对模型的影响相对公平,有助于模型更快地学习到特征的相对重要性。 - 激活函数相关 许多常用的激活函数(如Sigmoid、Tanh)在输入值过大或过小时,其梯度会变得非常小,接近于0(进入饱和区)。如果未归一化的特征值非常大,经过线性变换(Wx+bWx+b)后,输入到激活函数的值可能直接落入饱和区,导致梯度消失。这意味着该神经元的权重几乎无法更新,模型训练停滞 归一化后就可以将输入值限制在一个合理的范围内(例如,-1到1),避免了激活函数进入饱和区,从而有效缓解了梯度消失问题,使网络能够正常学习。
经过上面的解释,应该也能理解为什么每一次输出之后都要进行一次BN了,当然是因为输入经过处理之后可能又会使得特征参数变得大小不均匀
BN的步骤
- 求每一训练批次数据的均值
- 求每一训练批次数据的方差
- 使用求得的均值和方差对该批次训练数据进行归一化,获得0-1分布。其中
是为了避免除数为0时所使用的微小正数。 - 尺度变换和偏移:将
乘以 调整数值大小,再加上 增加偏移后得到 ,这里的 是尺度因子, 是平移因子。这一步是BN的精髓,由于归一化后的 基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,我们引入两个新的参数: 。 和 是在训练时网络自己学习得到的。 前三步保证了将值限制在一个合理的范围内(例如,-1到1)、减少梯度消失和梯度爆炸(因为落在Sigmode激活函数的区间比较靠中间,而不是两边),但是Sigmode激活函数的中间部分梯度变化率比较小,和线性没啥区别了,这就导致激活函数没起到激活的作用(都是线性了,那多加几层根本没有实质变化),所以需要第四步来适当扩大分布范围,保证原有数据的分布性,同时保证梯度的变化率,也就是保证非线性。
BN的优点
减少内部协变量偏移 BN 的归一化操作将每层的输入分布限制在一个稳定的范围内,减少了各层之间的协变量偏移,使得模型能够在深层网络中保持输入数据分布的稳定性,从而有效加速训练。
加速训练和提高收敛性 由于每一层的输入分布被稳定化,模型在训练时可以采用更高的学习率,同时 BN 也具有一定的正则化效果,使得模型更容易收敛。此外,BN 在一定程度上减轻了深度模型对参数初始化的敏感性,即使权重初始化较为随意,经过 BN 层后数据分布也能被重新调整到合理范围,从而加快收敛速度。
增加泛化能力,减少过拟合 BN 在每个 mini-batch 上动态计算均值和方差,这一过程中引入了随机性,具有一定的正则化效果,可以减少模型的过拟合。通常,采用 BN 的模型在不使用其他正则化方法(例如 dropout)的情况下也能够获得较好的泛化效果。
减小模型对超参数的敏感性(不怎么依赖权重初始化) 通过将输入分布标准化,BN 减少了模型对学习率、权重初始化和网络深度的敏感性。这样可以简化网络的超参数调优过程,减轻调参的工作量。
提高梯度传播的稳定性 BN 通过稳定每层的输入分布,确保了梯度的数值稳定性,减少梯度消失和爆炸的风险。这对于训练深层神经网络尤为重要,因为在没有 BN 的情况下,梯度可能在反向传播时逐渐消失或爆炸,导致模型难以有效训练。
BN的缺点
对小
的敏感性 BN 的归一化操作基于 mini-batch 的均值和方差,当 batch size 较小时,均值和方差的估计会变得不稳定,导致 BN 效果变差。为此,通常会使用大于 16 的 batch size 或改用 Layer Normalization(LN)、Instance Normalization(IN)和 Group Normalization(GN)等替代方法。 在循环神经网络(RNN)中的应用效果有限 BN 在循环神经网络中效果不如在卷积神经网络中显著。这是因为 RNN 的数据序列特性较强,batch 内不同样本在时间上的依赖性会影响均值和方差的稳定性。
推理阶段计算成本较高 在推理时,BN 需要使用训练阶段积累的均值和方差进行归一化操作,这增加了额外的计算成本。特别是对推理速度要求较高的应用场景,BN 可能会成为计算瓶颈。
BN同时起到了正则化作用,防止模型在训练集上过拟合,通常有BN的网络不再需要Dropout层
参数计算
总结
残差网络的出现突破了神经网络深度的束缚,改善了深度神经网络中的模型退化问题,使网络层数从数十层跃升至几百上千层,大幅提高了模型精度,通用性强适合各种类型的数据集和任务。残差块和shortcut这种优秀的设计也极大影响了后面的网络结构发展。
代码
GitHub - abinng/Blog-code: 用于存放我博客中的代码
进入后右上角可以给仓库一个Star哦~(´▽`ʃ♡ƪ)
















