ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

残差网络深度解析:从恒等映射到梯度消失的数学原理

残差网络深度解析:从恒等映射到梯度消失的数学原理

深度学习圈里有个老生常谈的现象:网络叠到几十层,训练集上的loss反而不如二三十层的浅网络——不是过拟合,而是纯粹没学好。早些年大家归咎于“梯度消失”,但Batch Normalization普及之后梯度问题缓解了很多,深层网络依然难以训练。直到ResNet出现,用一条“抄近道”的残差连接解决了这个问题。我当年第一次看ResNet论文时,最困惑的点在于:为什么仅仅是加了一个恒等映射(identity mapping),就能让训练难度出现断崖式下降?按说网络本身的表示能力并没有改变——多一个恒等分支既没增加非线性也没增加参数自由度,凭什么优化就变容易了?

这个问题的答案不在网络“能表示什么”,而在网络“容易学到什么”。换句话说,ResNet的贡献不是提高了模型容量上限,而是改变了优化的几何结构。这篇我从数学原理的角度拆一遍,把残差映射为什么优于传统的“直接拟合完整映射”(包括隐式地拟合恒等映射)讲清楚。适合已经会搭ResNet、但想弄明白它底层机理的读者,也适合正在训练深网络、想理解loss曲线异常原因的人。

1. 深层网络连“什么都不做”都学不会——恒等映射的真正难点

1.1 传统堆叠结构的参数空间里,恒等映射是一个“针尖”

先看一个最简单的思想实验。假设我们想训练一个深度为L的全连接网络,让它实现恒等映射:

[ f(x) = \sigma(W_L \cdots \sigma(W_2 \cdot \sigma(W_1 x + b_1) + b_2) \cdots + b_L) ]

理论上只要W都取单位阵、b取零,再来点ReLU之类的非线性(ReLU在正区间就是恒等),网络就能精确表示恒等映射。可问题是,在参数空间里,这个解不是一个“区域”,而是一个测度几乎为零的“点”。你稍微把任意一层的权重扰动一点,整个映射就和恒等函数差之千里。

用数学一点的话说,传统网络要学到恒等映射,等价于让一系列矩阵(在非线性作用下)的复合恰好约等于I。深度L越大,约束条件越多,满足条件的参数组合越“瘦”。SGD在参数空间里游荡时,想恰好落在这个针尖上,概率低到可以忽略。更麻烦的是,SGD的更新是局部的,它沿着梯度方向走一步,根本不知道远方的“针尖”在哪里。

这就是“传统恒等映射”问题的核心:不是表示不了,而是优化过程几乎不可能精确逼近那个解。ResNet论文里有句话我印象很深——“学习恒等映射的难度和训练一个深层网络本身的难度相当”。这句话翻译过来就是:你让深层网络学一个H(x)=x,它甚至很难做到什么都不学。

1.2 微小扰动在深度方向被非线性放大的直观图景

再换个视角看深度的效应。对传统堆叠网络,每一层相当于对输入做一次非线性变换。假设某一层的参数产生一个微小的扰动δ,输出变化量大致是:

[ | \Delta y | \approx | J | \cdot |\Delta x| + | \nabla_W f | \cdot |\delta| ]

J是该层的Jacobian。在ReLU网络中,J的谱范数可以轻易大于1。扰动经过多层传递,变化量按乘积累积:

[ |\Delta y_L| \sim \prod_{i=1}^L | J_i | \cdot |\Delta x_0| ]

深度一上来,这个乘积要么爆炸要么消失,参数空间被扭曲得极不规则。在这种崎岖的损失曲面里,SGD表现得像蒙着眼睛下山,每一步都踩不实。

ResNet的思路本质上是在说:既然完整映射太难学,那我让你只学“和恒等之间的差值”,把那个容易出问题的大背景“恒等映射”直接从结构上抽出来,不通过权重去拟合。网络只需要在小扰动尺度上做文章,优化难度自然下来了。

2. 残差分解的代数本质:把问题从“拟合H(x)”改成“拟合H(x)-x”

2.1 一个残差块的数学定义

ResNet中一个残差块的前向传播可以写成:

[ y = \mathcal{F}(x, {W_i}) + x ]

其中(\mathcal{F})是卷积、BN、ReLU的复合函数,通常包含两个或三个卷积层。传统非残差块则直接是:

[ y = \mathcal{F}(x, {W_i}) ]

表面上只差一个“+x”,但数学上这是两种完全不同的函数逼近策略。

传统块的目标是让(\mathcal{F}(x))逼近目标映射(\mathcal{H}(x))。残差块的目标是让(\mathcal{F}(x))逼近(\mathcal{H}(x) - x),而最终的输出是“恒等基线+残差修正”。关键在于:恒等映射不用任何一层参数去学习。网络天生就有一条路把x原封不动送到输出,残差分支只需要在“已经差不多对”的基础上做增量修正。

这就引出一个容易被忽略的结论——残差结构并没有改变网络的表示能力。理论上,只要残差分支能表示任意函数,(\mathcal{F}(x)+x)依然能表示任意函数。但表示能力等价不代表优化等价。它改变的是“解的先验”:强制把解空间锚定在恒等映射附近。实际任务中,很多问题的最优解本来就和输入具有强相关性,特征图的分布变化不剧烈,因而残差假设本身是个很合理的归纳偏置。

2.2 当目标恰为恒等映射时,残差结构的解是“零点”——一个天然稳定的最优解

继续上面的思想实验。让我们训练一个残差网络去学习恒等映射。此时目标变成:

[ \mathcal{F}(x) \rightarrow 0 ]

也就是让残差分支的权重矩阵趋近于零矩阵,或至少让残差分支在所有输入上输出零。这个解在参数空间中是一个“区域”,不是“点”:你只需要把卷积核初始化小一点或训练到足够接近零,它就稳定地表示恒等。

学过优化的读者都知道,零解往往是损失曲面里一个非常平稳的鞍点或极小值区域。它不像“很多非零权重精确抵消”那种解一样脆弱,稍微动一点参数依然近似满足要求。换句话说,恒等映射在残差参数化下从一个“苛刻的等式约束”变成了一个“宽松的区域吸引子”。这是“残差映射优于传统恒等映射”的第一个数学层面:目标投射到参数空间的方式不同,导致同样一个功能,一个难度高一个难度低。

2.3 从泰勒展开看残差的“一阶优势”

如果把某层变换看作对特征的微扰,残差网络的前向传播可以写成一个递推:

[ x_{l+1} = x_l + \mathcal{F}_l(x_l) ]

若(\mathcal{F}_l)的输出量级较小(实践中初始化时确实很小),则有近似:

[ x_L \approx x_0 + \sum_{l=0}^{L-1} \mathcal{F}_l(x_l) ]

这个形式很像欧拉法解常微分方程。它说明深层残差网络在行为上更像一个“多个微小增量逐步积分”的过程,而不是“一系列非线性变换反复复合”的过程。积分过程天然具有路径依赖性和平滑性,每次只改变输入的一小部分,信息不容易被破坏。传统堆叠网络则像是在玩传话游戏,每传一次都面目全非。

用信号处理的术语说,残差网络的输入信息有两条传播路径:一条是直达路径(恒等连接),一条是变换路径(残差分支)。直达路径保证信息底数不丢,变换路径学习增量。这种“干线+局部修正”的结构,和控制系统中的前馈加反馈补偿、数值分析里的预测-校正方法,本质上是一个思想。

3. 反向传播里的那个“1”——残差结构如何改写了梯度乘法链

3.1 从损失到特征的梯度递推

理解残差优势的第二层,也是被引用最多的一个视角,来自反向传播。设网络第l个残差块输入为(x_l),输出为:

[ x_{l+1} = x_l + \mathcal{F}_l(x_l, W_l) ]

损失L对(x_l)的梯度,由链式法则:

[ \frac{\partial L}{\partial x_l} = \frac{\partial L}{\partial x_{l+1}} \cdot \frac{\partial x_{l+1}}{\partial x_l} = \frac{\partial L}{\partial x_{l+1}} \left( I + \frac{\partial \mathcal{F}_l}{\partial x_l} \right) ]

注意这里出现了一个单位阵I。对比传统堆叠网络:

[ \frac{\partial L}{\partial x_l} = \frac{\partial L}{\partial x_{l+1}} \cdot \frac{\partial \mathcal{F}_l}{\partial x_l} ]

两式只差一个I,但性质天差地别。传统网络里梯度是层层“相乘”的,每一层Jacobian的谱范数若都小于1,梯度深层就会指数缩小;若都大于1,梯度就会指数爆炸。而残差网络的递推里,下一层梯度传播回上一层时,除了经过残差分支Jacobian之外,还有一条“直通路”让梯度原封不动返回,对应公式里的I。

3.2 梯度展开揭示的多路径本质

把残差网络的梯度递推展开到最浅层:

[ \frac{\partial L}{\partial x_l} = \frac{\partial L}{\partial x_L} \prod_{k=l}^{L-1} \left( I + \frac{\partial \mathcal{F}_k}{\partial x_k} \right) ]

这个乘积展开后是一个多项和,其中有一项是纯单位阵,对应的就是“梯度从最后一层直接传给最浅层”的最短路径。其他项则对应经过一个、两个、多个残差分支的“间接路径”。哪怕所有残差分支的Jacobian都趋近于零,最短路径上梯度依旧是(\partial L/\partial x_L),不会消失。

这就是“梯度高速公路”的数学本质:恒等路径上的梯度传播不经过任何非线性变换,也不被任何权重相乘。有人在可视化实验里发现,残差网络中浅层的梯度范数往往比非残差网络高出几个量级,正是因为这条最短路径的存在。

还可以从另一个角度理解:传统网络里,梯度从深层传到浅层要走L步,每步都乘以一个矩阵;残差网络里,梯度有机会“跳站”,一次直达。打个比方,传统网路是普通列车,每站必停且每站都要重新验票(矩阵相乘);残差网络是特快列车,有一节车厢可以从起点直达终点(恒等项),验票大爷对你这节车厢永远放行。

3.3 为什么有了BN还不够?

有人说,既然BN能缓解梯度消失,那还要残差连接干什么?这个问题的答案藏在BN的机制里。BN确实把每层输入的均值方差拉回来了,让激活值不饱和,但它改变不了“梯度需要穿过一系列权重矩阵才能回传”这个乘法链路。即使每层的特征归一化得很好,深层梯度在反向传播时依然要经过很多Jacobian连乘。BN解决了“每层内部的比例失调”,残差连接解决的则是“跨层传播的乘法收缩/膨胀”。两者解决的问题正交,难怪实践中best practice是“BN + 残差”一起用。

另外一个实操经验也能佐证:在深到上百层的纯堆叠+BN网络里,你打开训练日志会看到浅层参数几乎纹丝不动;而加上残差连接后,浅层梯度立刻“活”了过来。这是残差结构对梯度传播最直观的体现。

4. 损失曲面优化动力学:残差网络为何对SGD如此友好

4.1 残差块的Lipschitz性质:前向传播的稳定性

梯度只是优化的一部分,另一个重要部分是最优点周围损失曲面的几何形状。残差结构在数学上拥有一种很好的“保守性”:它可以看作在恒等映射上叠加一个具有小Lipschitz常数的变换。

设(\mathcal{F}_l)对输入是Lipschitz连续的,常数为(\gamma_l)。残差块的输入输出关系满足:

[ | (x + \mathcal{F}_l(x)) - (x' + \mathcal{F}_l(x')) | \le (1 + \gamma_l) |x - x'| ]

而传统网络块的对应关系是:

[ | \mathcal{F}_l(x) - \mathcal{F}_l(x') | \le \gamma_l |x - x'| ]

看起来一个多了个“1”,似乎Lipschitz常数反而更大。但注意,深度网络中真正可怕的是复合后的Lipschitz常数:

[ \prod_{l=1}^{L} (1 + \gamma_l) \approx 1 + \sum \gamma_l \quad \text{当}\gamma_l\text{很小时} ]

而传统网络的复合为:

[ \prod_{l=1}^{L} \gamma_l ]

如果(\gamma_l)略大于1,传统网络整个映射会对输入微小变化极端敏感,损失曲面局部斜率极陡;如果(\gamma_l)略小于1,信号又会在深层衰减殆尽。残差网络则把乘积中的“1”那份贡献始终保留,即使每层残差分支都很弱,复合函数依然接近恒等——这意味着损失曲面在参数扰动下不会因为深度加深而指数级恶化。

更朴素地说,残差网络保证了一件关键的事:深度增加不会自动导致前向传播和反向传播的病态化。这一条对SGD是决定性的。

4.2 损失曲面可视化告诉我们的几何事实

早先有人在二维平面上做过损失曲面的可视化对比实验,结论我印象极深:传统深网络的损失曲面就像梵高的星空,崎岖不平、布满锋利的谷脊,SGD解进去容易困在坏局部极小;残差网络的损失曲面则像是缓坡丘陵,视野开阔,SGD更容易沿着平缓的路径滑到好解。

这个现象背后的数学解释并不复杂。参数微扰(\delta)引起的输出变化中,传统网络的一阶近似是:

[ \Delta y \approx \sum_{l} J_{L \to l} \cdot \nabla_{W_l} \mathcal{F}_l \cdot \delta_l ]

其中(J_{L \to l})是深层对浅层的Jacobian连乘。由于这个连乘可以指数级放大或缩小,损失关于浅层参数的梯度尺度会变得极不平衡;有的方向梯度爆炸,有的方向梯度消失。优化器在这样一个高度各向异性的曲面上,学习率只能将就最小值。

残差网络中,(J_{L \to l})的主体是单位阵,输出对浅层参数的敏感度大致是均衡的。这意味着SGD的每一步更新在不同深度上“雨露均沾”,浅层参数不会因为梯度爆炸被一脚踢飞,也不会因为梯度消失而纹丝不动。你实际训练时会发现,残差网络可以用更大的学习率,收敛更平滑——这不是魔法,是几何结构变好了。

4.3 残差结构本质上降低了优化对初始化分布的敏感度

传统深网络对初始化极其敏感:初始化权重太大则梯度爆炸,太小则梯度消失,中间那一小段“合适区间”随深度增加而变窄。残差网络则不一样,因为前置“1”的存在,即使残差分支初始化为零,网络也不会训练不动——它至少是一个恒等映射,主梯度通路是通的。

这就引出实践中很实用的一个技巧:残差网络的最后一层卷积或BN可以被初始化为零或极小值,让初始阶段网络约等于恒等映射,再逐步“放权”给残差分支。这种“先恒等、后学习”的策略在数学上是合理的:既然残差分支的使命是修正,那么从零修正开始最稳定。很多实现里普通残差块虽然不会直接把最后一层置零,但在预训练或迁移时,这种先验会在潜意识层面帮助优化。

5. 从数学再看ResNet变体的成败:捷径形式决定梯度与信息流

5.1 为什么Pre-activation(预激活)能更干净

ResNet原版中恒等连接跨过了一个“conv-BN-ReLU-conv-BN-ReLU-conv”序列,BN作用于恒等捷径后的加法之前。理论上,这个BN会微调恒等路径输出的尺度,但不会阻断它。后来有人发现把BN移到卷积之前(即预激活),效果更好,理由是此时恒等路径上完全不经过任何归一化或非线性,梯度传播路径被“纯化”了。从公式上看,预激活残差块的梯度递推严格满足:

[ \frac{\partial x_{l+1}}{\partial x_l} = I + \frac{\partial \mathcal{F}}{\partial x_l} ]

而原版残差块里由于BN在加法之后,理论上还存在一些额外缩放因子。这个细微差别在深层(比如几百层)时会累积成可见的训练稳定性优势。这其实就是数学的洁癖换来了工程的红利。

5.2 捷径缩放、非线性捷径为什么常常失败

有人尝试过给恒等捷径乘一个0.5的系数,或者换成1×1卷积,效果通常不如原版。从数学上这是必然的。若捷径是(g(x))而非(x),梯度递推变成:

[ \frac{\partial x_{l+1}}{\partial x_l} = \frac{\partial g}{\partial x_l} + \frac{\partial \mathcal{F}}{\partial x_l} ]

如果(g)是线性变换且谱范数不是1,那么梯度连乘中“主项”的范数不再是1,而是(\sigma_{\max}(G)^L)。只要0.5,300层之后梯度就缩小为原来的一半的300次方,消失得无影无踪;如果系数大于1,则容易爆炸。所以“捷径必须是恒等”这个结论不是拍脑袋,而是为了同时保证前向信息尺度和反向梯度尺度的稳定性。

非线性捷径同理,它破坏了梯度主路径的线性性质,让“1”不再是一个精确的常数,反而为梯度引入了额外Jacobian,深层训练重新变得不稳定。某些变体确实work,但那些work的背后往往额外加了复杂的归一化技巧——本质上是在为破坏“1”的行为买单。

5.3 DenseNet与Transformer:残差思想的两种推广

DenseNet的密集连接可以看成“把所有层的残差都直接连向后续所有层”,梯度从任意深层都能直达任意浅层。它比串行残差连接更激进,多路径展开后项数更多,梯度传播路径更长更多样。缺点是特征图复用导致内存开销大。Transformer的每一个子层(注意力、前馈)都带了一个Add & Norm,本质上也是残差连接。深层Transformer能训练起来,同样依赖那个“1”带来的梯度直通。如果你把Transformer里的残差去掉,大概率loss直接放飞自我。理解这个原理后再看那些“为什么Transformer需要残差”的问题,答案其实早就写在ResNet的数学里了。

6. 理论之外:我在调试深网络时看到的实际差异

6.1 用输入输出相似度判断残差块是否“干活”

训练残差网络时,我习惯在每几个epoch记录一下随机选取的某个中间层特征图和输入特征的余弦相似度。如果某层残差块长期保持输出≈输入,说明该层的残差分支贡献微弱,基本在“划水”。传统网络里我很难这么直观地判断——因为根本没有“恒等基线”可以对照。残差结构让“每层学了多少”变成了一个可以观测的量,这对调试模型很有帮助。

有一回我训练一个图像分类模型,发现后十几个残差块的相似度接近0.99,说明网络实际上只用了前面几十层做特征提取,后面的层几乎处于恒等模式。我根据这个观察剪掉了一部分尾部块,重新微调,准确率几乎没掉,反而省了30%推理时间。这是残差结构在工程上意外赠送的“可解释性”。

6.2 大学习率为什么在ResNet上行得通

另一个经验是,残差网络往住能承受比较大的初始学习率。细想这和第二节的分析完全对得上:因为损失曲面更平滑,梯度尺度在不同深度间更均衡,SGD不会因为某些方向的爆炸梯度而震荡。我自己的经验是,换到非残差对比模型时,同一份代码同一份数据,线性缩放学习率规则经常失效;而残差结构下,从0.1到0.3的学习率扫描,结果往往都稳得住。这不是玄学,是损失曲面几何变好的直接体现。

6.3 残差网络并非万能,但理解数学让你知道它的边界

值得泼一盆冷水:残差连接不是所有病都能治。它解决的是“深层叠加导致的信息衰减和梯度病态”,但解决不了“数据太少导致过拟合”,也解决不了“任务本身不适合深层特征”。如果网络已经50层了训练还是上不去,先检查数据、标签、学习率、归一化策略,不要盲目加深再指望残差结构兜底。

我个人的体会是,理解残差映射的数学原理之后,看很多网络结构会有一种“吊诡的清晰感”:注意力机制里的跳跃连接、状态空间模型里的动力学离散化、甚至多模态模型里的门控残差,本质上都是在控制“信息至少有一条不被改变的路径”和“让变换始终以增量的方式引入”。这条思路,远比背下“残差网络解决梯度消失”一句话更有价值。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进