想象一栋一百层高的公司大楼,每一层坐着一位文件专员,负责把送来的文件再加一道工。一楼刚录入的原始资料,要一层层送上去,每层改一版。可这栋楼没有电梯,只有楼梯。更麻烦的是:顶层大老板要往下传达修改意见时,只能靠一层层口头转述——每转一层就含糊一点、声音小一点,等传到一楼,已经气若游丝,底层员工根本听不清要改什么。 这栋楼,就是没有残差连接的深度神经网络。楼层是网络层,向上送文件是前向传播,向下传口令是反向传播的梯度。楼层越高,口信越弱——这就是“梯度消失”。于是人类一度认为:网络再深也没用,底层永远学不到东西。 ResNet 的破局思路简单得惊人:给大楼装一部直达滑梯。大老板的口令可以顺着滑梯从顶层直通底层,一字不差;每一层专员只需要在原文件上做小幅修改,原件本身永远有备份在滑梯上。这部滑梯就是残差连接(跳跃连接)。它让网络可以堆到一百多层甚至一千多层,底层照样能收到清晰的学习信号。2015 年,ResNet 凭此横扫 ImageNet 冠军,也从此改写了深度学习的历史。

岗位关联

残差连接是深度学习从“练不动”到“能堆千层”的分水岭。读懂它,你就掌握了几乎所有现代神经网络(CNN 与 Transformer)的骨架设计逻辑,这是每一位 AI 工程师理解现代架构的必修课。

目录
  1. 可视化演示
  2. 深度之困
  3. 残差思想
  4. 网络结构
  5. 梯度通路
  6. 版本演进
  7. 实战应用
  8. 意义影响
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示残差块的结构设计(主路径+跳跃连接)及残差连接如何解决深层网络梯度消失问题,对比有无线连接的梯度传播效果。

本节配有交互动效(进入视口后自动加载,约 3KB)。

残差块结构 主路径:输入经两层卷积+ReLU变换,学习残差映射F(x) 跳跃连接:输入x直接加到主路径输出,形成H(x)=F(x)+x 当最优解接近恒等映射时F(x)趋近零,权重推向零比学习恒等映射容易 H(x) = F(x) + x 残差连接使网络至少不比浅层差。

深度之困

这栋百层大楼只有楼梯、没有电梯。顶层大老板要修改一楼的文件,只能靠每一层的工作人员口头转述,“把第三段删掉”传到第七层变成“把第三行改一下”,传到三楼已经变成“文件有问题”,等传到一楼,只剩下“嗯嗯啊啊”的模糊气音。楼盖得越高,这种失真就越致命——底层员工永远听不到准确的指令,大楼再高也只是摆设。

在神经网络里,这个“传话”的过程就是反向传播。每一层网络相当于一个加工专员:前向传播时文件(特征)一层层向上加工,反向传播时,损失信号(大老板的不满)要一层层向下传回,告诉每一层的参数应该往哪个方向更新。层数一多,信号就传不动了,这就是众所周知的 梯度消失(Vanishing Gradient)。

数学上,反向传播靠的是链式法则:损失对第一层输入的梯度,等于相邻层梯度一个个乘起来。麻烦在于,早期的 sigmoid 或 tanh 激活函数,导数最大也只有 0.25 或 1,几十个小数的连乘,结果会指数级趋近于零。更反直觉的是论文中的 退化现象(Degradation):56 层的普通网络,训练误差居然比 20 层还要高。这不是过拟合,而是深层网络在优化层面根本“练不动”。

所以 2015 年之前,卷基层数大多停在 10~20 层。设计师们不是不想盖高楼,而是每次一盖高,底层员工就集体“失聪”。深度学习的瓶颈,不是想象力,而是这架“楼梯”本身。

∂L∂x1=∏i=1n−1∂xi+1∂xi×∂L∂xn\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{x}_1} = \prod_{i=1}^{n-1} \frac{\partial \mathbf{x}_{i+1}}{\partial \mathbf{x}_i} \times \frac{\partial \mathcal{L}}{\partial \mathbf{x}_n}
通俗说:梯度是“一层层相乘”传下来的,每乘一次就小一点,层数多了自然就消失;这就是大楼里“口令越传越弱”的数学写照。
  1. 损失对首层的梯度$\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{x}_1}$ 表示损失函数 $\mathcal{L}$ 对第 1 层输入 $\mathbf{x}_1$ 的偏导数,它衡量底层能不能收到足够大的学习信号。
    ∂L∂x1\frac{\partial \mathcal{L}}{\partial \mathbf{x}_1}
  2. 链式法则展开$\displaystyle \prod_{i=1}^{n-1} \frac{\partial \mathbf{x}_{i+1}}{\partial \mathbf{x}_i}$ 是把从第 1 层到第 n 层的相邻层导数全部乘起来,层数越多,乘的次数越多。
    ∏i=1n−1∂xi+1∂xi\prod_{i=1}^{n-1} \frac{\partial \mathbf{x}_{i+1}}{\partial \mathbf{x}_i}
  3. 雅可比矩阵连乘$\displaystyle \frac{\partial \mathbf{x}_{i+1}}{\partial \mathbf{x}_i}$ 是第 i 层到第 i+1 层的雅可比矩阵;当激活函数导数小于 1 时,连乘结果随深度指数衰减。
    ∂xi+1∂xi\frac{\partial \mathbf{x}_{i+1}}{\partial \mathbf{x}_i}
  4. 末尾损失项$\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{x}_n}$ 是损失对最顶层的梯度,它本身数值有限,却被前面 n-1 次连乘不断稀释。
    ∂L∂xn\frac{\partial \mathcal{L}}{\partial \mathbf{x}_n}

残差思想

新设计师换了个思路:不让每一层专员“从零设计一份完美文件”,而是让他们只负责“在原文件上做增补批注”。原件由滑梯直接传上去,每一层拿到的是“原件 + 上一层的修改意见”,然后在上面再添自己的批注。这样,每层的任务从“我要设计出完整答案”变成了“我只需要把差距补上一点点”。

这个思想落到数学上,就一行字:把网络要学的映射 $\mathcal{H}(\mathbf{x})$ 拆成“恒等映射 + 残差函数”。

所谓 残差(Residual),就是“目标减去输入”的差值——$\mathcal{F}(\mathbf{x}, \{W_i\}) = \mathcal{H}(\mathbf{x}) - \mathbf{x}$。如果目标映射恰好是恒等映射(原文件已经足够好),那残差支路只需把 $\mathcal{F}$ 推成 0 即可,这比用一堆非线性层去硬拟合“原样不动”要容易得多。用生活的话说:在一份已经合格的答卷上“什么都不改”,比“重新抄一遍且一字不差”简单太多。

正是这个“至少不比浅层差”的性质,让深度从此有了意义:浅层网络的能力可以被深层网络“完整包含”,深层只是在其上不断精修。

从此,盖楼逻辑变了:每一层专员不再压力山大——改不动就什么都不改,反正原件会原样抵达顶楼。这栋楼第一次做到了“盖得越高,至少不会更差”。

H(x)=F(x,{Wi})+x\displaystyle \mathcal{H}(\mathbf{x}) = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x}
通俗说:残差块把“学整个函数”换成了“学变化量”,最优情况下残差趋近于零,网络退化成恒等映射也能稳稳兜底。
  1. 期望映射$\mathcal{H}(\mathbf{x})$ 是网络整体想逼近的目标函数,也就是这份文件最终应该变成的样子。
    H(x)\mathcal{H}(\mathbf{x})
  2. 残差子网络$\mathcal{F}(\mathbf{x}, \{W_i\})$ 是带参数 $W_i$ 的子网络(通常是几个卷积层),它负责学习“还需要改多少”。
    F(x,{Wi})\mathcal{F}(\mathbf{x}, \{W_i\})
  3. 恒等捷径$+\mathbf{x}$ 表示输入原样加回,不做任何变换,这是滑梯上那份“原件”。
    +  x+\;\mathbf{x}
  4. 残差即差值$\mathcal{F}(\mathbf{x}, \{W_i\}) = \mathcal{H}(\mathbf{x}) - \mathbf{x}$,残差支路不学全量映射,只学“目标与输入的差”。
    F(x,{Wi})=H(x)−x\mathcal{F}(\mathbf{x}, \{W_i\}) = \mathcal{H}(\mathbf{x}) - \mathbf{x}

网络结构

滑梯的施工图其实非常朴素。一个标准的残差块(Basic Block)长这样:先把输入 $\mathbf{x}$ 送进两个 3×3 卷积层(中间夹 ReLU 激活),得到残差支路的输出 $\mathcal{F}(\mathbf{x}, \{W_i\})$;然后在块的外面搭一条“捷径”,把输入 $\mathbf{x}$ 直接加到支路输出上,作为整个块的输出。这条捷径,就是论文里说的 shortcut connection(跳跃连接)。

前向计算可以写成一个公式:

当输入输出的形状完全一致时,$W_s$ 就是单位阵,式子退化为 $\mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + \mathbf{x}$,逐元素相加,通道数不变。但网络在加深时通常会在某几层把通道数翻倍、把特征图尺寸减半,这时捷径上就要加一个 1×1 卷积做“投影”,即 $W_s \mathbf{x}$,既匹配通道数,又可以通过 stride=2 完成降采样。

以 ResNet-34 为例,它由 4 个阶段组成,每个阶段的残差块数量为 3、4、6、3,通道数从 64 涨到 512。结构上只有两种“积木”:直筒块(两个 3×3)和带降采样的投影块,简单到可以用一张表画完。

这份施工图简单到什么程度?一个实习生看五分钟就能复现。而正是这种“朴素到极致”的设计,让大楼从图纸变成了现实——因为每一层都只需要做加法,工程上几乎没有额外负担。

y=F(x,{Wi})+Wsx\displaystyle \mathbf{y} = \mathcal{F}(\mathbf{x}, \{W_i\}) + W_s \mathbf{x}
通俗说:维度一致就直接相加,维度不一致就先用 1×1 卷积把滑梯“接驳”到对应尺寸,再相加。
  1. 块输出$\mathbf{y}$ 是残差块的输出,它会作为下一个块的输入,继续向上传递。
    y\mathbf{y}
  2. 残差支路$\mathcal{F}(\mathbf{x}, \{W_i\})$ 是块内卷积层堆叠学到的残差变化量,形状与输入一致。
    F(x,{Wi})\mathcal{F}(\mathbf{x}, \{W_i\})
  3. 投影捷径$W_s \mathbf{x}$ 是捷径上的 1×1 卷积投影,负责在维度不匹配时对齐形状。
    WsxW_s \mathbf{x}
  4. 形状不变性逐元素相加要求三个张量形状相同,即 $\mathbf{y}, \mathbf{x}, \mathcal{F}$ 都属于 $\mathbb{R}^{C \times H \times W}$。
    y,  x,  F∈RC×H×W\mathbf{y},\;\mathbf{x},\;\mathcal{F} \in \mathbb{R}^{C \times H \times W}

梯度通路

现在关键问题来了:大老板的口令从顶楼发下来,有了滑梯之后,底层真的能听清吗?答案是能,而且这是残差最漂亮的地方。每层专员在传话时可能会“开小差”(旁路的梯度会变化、会衰减),但滑梯上的原件副本(输入的恒等路径)永远是一份原封不动的指令。

反推数学就会发现,梯度在通过一个残差块时,被分成了两条路:一条走残差支路 $\mathcal{F}$,这部分的梯度确实还会受层内权重影响、可能变小;另一条走恒等捷径,梯度乘的系数是 1,原封不动地穿过去。两条路的梯度最终相加,再继续往下一层传。

这个式子里的“1“就是整篇论文的灵魂。即使旁路项 $\frac{\partial \mathcal{F}}{\partial \mathbf{x}}$ 因为某些原因趋近于零,恒等项”1”仍然保证梯度完整地回传到上一层。如果把 L 个残差块叠起来,梯度传播因子就是 $\prod_{k}\left(1 + \frac{\partial \mathcal{F}_k}{\partial \mathbf{x}_k}\right)$——每个因子都大于等于 1,连乘根本不可能指数衰减。

这就好比大楼每一层都装了滑梯,大老板的指令从顶楼一口气滑到一楼,沿途的专员再怎么“开小差”,也没人能拦下滑梯上的原件。梯度消失这个困扰学界多年的顽疾,就这样被一条“加法捷径”治好了。

∂L∂x=∂L∂y×(1+∂F(x,{Wi})∂x)\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{x}} = \frac{\partial \mathcal{L}}{\partial \mathbf{y}} \times \left( 1 + \frac{\partial \mathcal{F}(\mathbf{x}, \{W_i\})}{\partial \mathbf{x}} \right)
通俗说:梯度 = 上游信号 ×(1 + 旁路)。那个"1"是滑梯给的保底,让信号至少不减半地到达底层。
  1. 上游梯度$\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{y}}$ 是损失对残差块输出 $\mathbf{y}$ 的梯度,也就是楼上已经传下来的信号。
    ∂L∂y\frac{\partial \mathcal{L}}{\partial \mathbf{y}}
  2. 恒等项 1$1$ 来自捷径 $+\mathbf{x}$ 对 $\mathbf{y}$ 的导数,它保证梯度有一条永不衰减的通道。
    11
  3. 旁路项$\displaystyle \frac{\partial \mathcal{F}(\mathbf{x}, \{W_i\})}{\partial \mathbf{x}}$ 是残差支路对输入的导数,这部分会被层内权重压缩或放大。
    ∂F(x,{Wi})∂x\frac{\partial \mathcal{F}(\mathbf{x}, \{W_i\})}{\partial \mathbf{x}}
  4. 连乘保底$\displaystyle \prod_{k} \left( 1 + \frac{\partial \mathcal{F}_k}{\partial \mathbf{x}_k} \right)$ 说明多层叠加后,每个因子都有"1"兜底,乘积不会趋近于零。
    ∏k(1+∂Fk∂xk)\prod_{k} \left( 1 + \frac{\partial \mathcal{F}_k}{\partial \mathbf{x}_k} \right)

版本演进

楼越盖越高,施工成本也在爆炸。如果每一层都用两个 3×3 卷积直接堆,到了 50 层以上,参数量和计算量会大到工业界无法承受。设计师的解决办法非常“抠门”:大文件不要整份处理,先缩印成小抄,在小抄上做修改,最后再放大回原尺寸。

这就是 Bottleneck(瓶颈)残差块:先用 1×1 卷积把 256 个通道压缩到 64 个(缩印),然后用 3×3 卷积在低维空间做主要计算,最后再用 1×1 卷积把 64 个通道升回 256 个(放大)。整个块的参数量,比直接在 256 通道上做两个 3×3 卷积少了一个数量级:

于是 ResNet 家族形成了清晰的产品线:ResNet-18/34 面向轻量场景,用直筒块;ResNet-50/101/152 面向高精度场景,用瓶颈块。其中 ResNet-152 在 ILSVRC 2015 上以 3.57% 的 Top-5 错误率夺冠,比第二名低了一大截,而且层数越深,优势越明显。

有了“缩印”工艺,152 层甚至 1001 层的大楼不再是科幻。施工队手里有了两张王牌:滑梯解决训练问题,瓶颈解决成本问题——深度与成本第一次可以兼得。

Pbottleneck=256×64+9×64×64+64×256=69632\displaystyle P_{\text{bottleneck}} = 256 \times 64 + 9 \times 64 \times 64 + 64 \times 256 = 69632
通俗说:瓶颈块 = 先压缩再处理再还原,用 1×1 卷积做“缩印”和“放大”,把昂贵的 3×3 计算放在低维空间里完成。
  1. 降维卷积$256 \times 64$ 是第一个 1×1 卷积的参数量,把 256 通道压到 64,这一步就是“缩印”。
    256×64256 \times 64
  2. 低维计算$9 \times 64 \times 64$ 是 3×3 卷积在 64 通道上的参数($9=3\times3$),核心计算在低维空间完成。
    9×64×649 \times 64 \times 64
  3. 升维卷积$64 \times 256$ 是最后一个 1×1 卷积的参数量,把 64 通道恢复成 256,保证输出形状与输入一致。
    64×25664 \times 256
  4. 总参数量$P_{\text{bottleneck}} = 69632$,对比直筒方案 $2 \times 9 \times 256 \times 256 = 1179648$,参数约为其 1/17。
    Pbottleneck=69632P_{\text{bottleneck}} = 69632

实战应用

大楼盖好之后,人们发现一个意外之喜:前几十层的装修风格是高度通用的。一楼的边缘检测、五楼的纹理识别、二十楼的物体部件感知,几乎换个行业都能直接用。真正需要定制的,只有顶楼那几层“会议室”(任务头)。于是,残差网络成了工业界的“标准毛坯房”。

在实战中,ResNet 主要在三个位置出现。第一是图像分类骨干:把 ResNet 当特征提取器,接一个全局池化加全连接层,就能做商品识别、内容审核;第二是目标检测与分割骨干:Faster R-CNN、YOLO 等检测器普遍把 ResNet 作为 backbone,配合 FPN 把多层特征融合起来;第三是迁移学习:把 ImageNet 上预训练好的 ResNet 拿过来,冻结前几层、微调后几层,在小数据集上也能快速收敛。

这个广泛“复用”的能力,在数学上也有保障。把残差网络沿深度方向“展开”来看,深层网络其实在逐层叠加修正量,浅层学到的特征永远不会被丢弃。正是这种“特征不丢”的特性,让预训练-微调成为深度学习的标准工作流。

今天,你在电商平台搜商品、用手机相册做分类、看自动驾驶识别障碍物,背后大概率都站着一栋“装了滑梯的大楼”。残差网络不是某一个产品,而是这些产品共同的“地基”。

Top-5 错误率ResNet-152=3.57%\displaystyle \text{Top-5 错误率}_{\text{ResNet-152}} = 3.57\%
通俗说:预训练 ResNet 就像一栋装修好前几十层的大楼,新业务只需改装顶楼会议室;残差保证了搬到哪里,底层结构都稳定可靠。
  1. 指标定义Top-5 错误率指模型预测的前 5 个类别中不包含真实类别的样本占比,是 ImageNet 当年的主指标。
    预测前 5 类包含真实类别的样本数样本总数\frac{\text{预测前 5 类包含真实类别的样本数}}{\text{样本总数}}
  2. 模型标识$\text{ResNet-152}$ 表示 152 层的残差网络,是当年 ImageNet 竞赛的参赛模型。
    ResNet-152\text{ResNet-152}
  3. 冠军成绩$3.57\%$ 是 ResNet-152 在 ILSVRC 2015 上的 Top-5 错误率,一举夺冠。
    3.57%3.57\%
  4. 人类对比$5.1\% \rightarrow 3.57\%$,模型的错误率首次稳定低于人类水平(约 5.1%)。
    5.1%→3.57%5.1\% \rightarrow 3.57\%

意义影响

滑梯方案在 2015 年 ImageNet 夺冠后,整个行业一夜之间“人人装滑梯”。此后的经典架构——ResNeXt 的分组残差、DenseNet 的密集连接、MobileNet 的倒残差、甚至 Transformer 里的残差子层——无一不是对“恒等捷径 + 增量学习”这一范式的继承与变形。

残差带来的最深刻影响,是让“深度”从一句口号变成了工程现实。在残差出现之前,20 层是网络的天花板;残差出现之后,1001 层的 ResNet 可以正常训练。它把人们对网络容量的想象空间彻底打开了。把残差网络沿深度方向展开,可以看到这样一个简洁的结构:

这个式子告诉我们:不管网络堆多深,最终的输出都等于最初的浅层特征 $\mathbf{h}_0$ 加上每一层残差块的修正量之和。深层网络的表达能力“包含”浅层网络,而不是另起炉灶——这就是为什么残差能保证“深层至少不比浅层差”的根本原因。

回望 2015 年,ResNet 这篇论文只有一句话的核心洞察:让梯度走滑梯。但它撬动的是整个深度学习大厦的承重结构。从那以后,深度不再是稀缺资源,而是基础设施——这栋楼的故事,也成了 AI 历史上最漂亮的“减法变加法”。

hL=h0+∑i=0L−1F(hi,Wi)\displaystyle \mathbf{h}_L = \mathbf{h}_0 + \sum_{i=0}^{L-1} \mathcal{F}(\mathbf{h}_i, W_i)
通俗说:深层网络 = 浅层网络 + 一堆精修补丁。补丁可以多可以少,但原作永远在。
  1. 起点特征$\mathbf{h}_0$ 是网络最浅层的输出,比如第一层卷积得到的边缘特征。
    h0\mathbf{h}_0
  2. 逐块修正$\mathcal{F}(\mathbf{h}_i, W_i)$ 是第 i 个残差块学到的增量,相当于每层专员在原文件上添的批注。
    F(hi,Wi)\mathcal{F}(\mathbf{h}_i, W_i)
  3. 累加求和$\displaystyle \sum_{i=0}^{L-1}$ 把所有 L 个残差块的修正量累加起来,得到最终的深层特征。
    ∑i=0L−1\sum_{i=0}^{L-1}
  4. 深层不劣于浅层$\mathbf{h}_L = \mathbf{h}_0 + \sum_{i=0}^{L-1} \mathcal{F}(\mathbf{h}_i, W_i)$ 说明深层输出永远保留 $\mathbf{h}_0$,表达能力单调不降。
    hL=h0+∑i=0L−1F(hi,Wi)\mathbf{h}_L = \mathbf{h}_0 + \sum_{i=0}^{L-1} \mathcal{F}(\mathbf{h}_i, W_i)

AI 应用场景

电商商品图像分类

阶段:模型训练与特征提取

解决的问题:传统 CNN 网络加深后梯度消失,浅层网络又学不到细粒度特征,导致品类繁多的商品识别准确率上不去,且训练过程极其不稳定。

具体案例:某电商平台用 ImageNet 预训练的 ResNet-50 作为骨干,在其后接一个全局池化和分类头,再在百万级商品图上微调。残差结构保证了训练时底层梯度稳定回传,最终在 6000 多个细类上的 Top-1 准确率提升了 11 个百分点,而且从零训练也能稳定收敛。

自动驾驶目标检测

阶段:模型推理与骨干特征提取

解决的问题:目标检测既要高层语义判断“这是什么”,又要底层细节判断“物体边界在哪”,需要一个既深又稳的骨干网络来同时提供多层特征。

具体案例:Faster R-CNN 与 YOLO 系列普遍采用 ResNet 作为 backbone,配合特征金字塔(FPN)把 ResNet 各阶段的特征图融合使用。残差连接保证深层骨干在大分辨率输入下梯度依然稳定,使车辆、行人、交通标志的检测在雨雾等复杂场景下保持高召回。

医疗影像小样本迁移学习

阶段:迁移学习与模型微调

解决的问题:医学影像标注样本稀缺,从零训练深层网络必然过拟合或梯度不稳;直接套用浅层网络又达不到诊断精度。

具体案例:研究团队用 ImageNet 预训练的 ResNet-34,冻结前三个阶段的卷积层,只微调最后一个阶段和分类头,在几千张眼底 OCT 图像上就训练出了可用的病灶分类模型,训练时间从几天缩短到几小时。残差的“特征不丢”特性,让通用特征在新任务上依然有效。

Python 演示

python45 行
import numpy as np  def block_forward(x, w, b, residual=True):    """一个网络块:全连接 + tanh 激活,可选残差连接"""    h = np.tanh(np.dot(w, x) + b)    if residual:        return x + h          # 残差连接:输入直接加回输出    return h  def first_grad_norm(x0, blocks, residual):    """用数值梯度估算第一层输入处的梯度范数"""    eps = 1e-6    grad = np.zeros_like(x0)    for i in range(x0.size):        xp = x0.copy()        xm = x0.copy()        xp[i] += eps        xm[i] -= eps        for w, b in blocks:            xp = block_forward(xp, w, b, residual)            xm = block_forward(xm, w, b, residual)        loss_p = np.sum(xp * xp)        loss_m = np.sum(xm * xm)        grad[i] = (loss_p - loss_m) / (2 * eps)    return np.linalg.norm(grad)  np.random.seed(42)depth = 16dim = 6blocks = []for _ in range(depth):    w = np.random.randn(dim, dim) * 0.25 / np.sqrt(dim)    b = np.random.randn(dim) * 0.01    blocks.append((w, b)) x0 = np.random.randn(dim) * 0.5n_plain = first_grad_norm(x0, blocks, residual=False)n_res = first_grad_norm(x0, blocks, residual=True) print("普通网络 16 层后首层梯度范数: %.6e" % n_plain)print("残差网络 16 层后首层梯度范数: %.6e" % n_res)print("残差让梯度保持倍数: %.1e 倍" % (n_res / n_plain))
目的:用 16 层带 tanh 激活的小型网络做对照实验,直观展示普通网络第一层梯度几乎消失,而残差网络第一层梯度依然强壮。
  1. def block_forward(x, w, b, residual=True):定义通用的网络块前向计算,residual 参数控制是否启用残差。
  2. return x + h这就是残差连接的代码形态:输入 x 与非线性变换结果 h 逐元素相加。
  3. loss_p = np.sum(xp * xp)用输出向量的平方和作为标量损失,梯度就对这个损失求导。
  4. grad[i] = (loss_p - loss_m) / (2 * eps)中心差分法计算数值梯度:分别给第 i 维加/减微小扰动,比较损失变化。
  5. np.linalg.norm(grad)计算第一层输入处的梯度范数,衡量“底层收到信号的大小”。
  6. blocks.append((w, b))每层权重只缩放到 0.25/sqrt(6) 左右,保证谱范数小于 1,模拟真实深层网络里梯度逐层衰减的条件。
  7. print("残差让梯度保持倍数: %.1e 倍" % (n_res / n_plain))打印两种网络首层梯度范数的比值,直观看出残差把梯度从“消失”拽回“正常”。

常见误区

误区我一开始以为残差连接就像接力棒,把输入 x 原封不动地“传”给下一层网络,让下一层接着处理,相当于把输入复制了一份继续往前送。

正解残差连接不是“把 x 传给下一层”,而是“把 x 与残差支路输出 F(x) 做完逐元素相加后,把结果 y = F(x) + x 传给下一层”。下一层拿到的是加法结果,不是原始 x 本身。真正的“原样传递”发生在块内的加法节点上,原件只是被“抄送”了一份参与相加,并不是绕过整个块直接当下层输入。

为何常见:“跳跃连接”“shortcut“这类名字很容易让人想到”抄近道直接转发”,忽略了它本质是并行支路求和的数学结构。

误区跳层连接嘛,把浅层特征和深层特征拼在一起,通道数变多,信息更丰富,DenseNet 不就是这么干的吗?ResNet 应该也一样。

正解ResNet 用的是逐元素相加(element-wise add),通道数完全不变,只是相同位置的数值求和;DenseNet 用的才是通道拼接(concat),输出通道数会膨胀。两者有本质区别:加法让恒等路径的导数是精确的 1,从而带来梯度保底;拼接没有这个数学性质,它解决的是特征复用而不是梯度通路问题。

为何常见:两者都被统称为“跨层连接”,初学者只记住了“跳层”的直觉,忽略了 ResNet 最核心的“加法”与“导数 1”才是关键。

误区ResNet 论文不是说 152 层、1001 层都能训练吗?那深度就完全不是问题了,我随便堆一万层也能拿更好精度。

正解残差解决的是梯度通路问题,不代表深度没有其他代价。深层网络的训练仍然依赖 Batch Norm、合理的初始化、学习率调度和数据增强;而且超过一定深度后(如千层以上),即使梯度不消失,优化也会进入新的困难区,精度未必继续提升。残差让“深层至少不比浅层差”,但不等于“越深一定越好”。

为何常见:论文的冲击性标题“152 层”“千层”给人留下“深度自由”的印象,忽略了论文里同样讨论了超深层仍存在的优化边界。

误区梯度走恒等捷径永远倍增不了也衰减不了,那残差支路 F(x) 岂不是可有可无?干脆所有层都直接跳过去算了。

正解恒等项“1“只保证”有一条不衰减的通路“,但网络真正学到的知识全部来自残差支路 F(x)。如果 F(x) 恒为 0,整个网络退化为恒等映射——输入是什么输出就是什么,什么也学不到。准确的说法是:残差把”梯度能不能传回来“和”网络能不能学好”两件事解耦了,前者靠恒等项兜底,后者依旧靠支路学习能力。

为何常见:人们容易把“梯度能传回去”等同于“模型有表达能力”,其实一个是运输问题,一个是生产问题。

面试题

Q1. 下列关于残差块输入输出关系的描述,正确的是?

单选题 · easy

  • A.将输入与输出在通道维拼接
  • B.把输入输出做逐元素相乘
  • C.将输入与输出逐元素相加← 正确答案
  • D.把输出与输入做逐元素相减

答案:C。残差块的核心是 y = F(x) + x,输入与残差支路输出逐元素相加。拼接是 DenseNet 的做法,相乘是注意力门控的做法,相减则完全颠倒了残差“加回原件”的设计意图。记住:滑梯是“加”出来的,不是“拼”出来的。

Q2. 下列属于 ResNet 解决的核心问题的是?

单选题 · easy

  • A.训练数据量不足导致模型欠拟合
  • B.过拟合导致深层网络测试误差上升
  • C.梯度消失与退化导致网络难训练← 正确答案
  • D.计算资源消耗太大导致难部署

答案:C。ResNet 针对的是深层网络“练不动”的问题:梯度消失让底层收不到信号,退化现象让 56 层训练误差高于 20 层,二者都是优化层面的困难。过拟合和数据问题不是 ResNet 的出发点。这就像大楼盖高了底层听不见指令,而不是大楼租户太多。

Q3. 残差块中“恒等映射”的含义是?

单选题 · mid

  • A.让每一层网络学习单位矩阵
  • B.将输入 x 原样加回块输出← 正确答案
  • C.把梯度范数限制为固定数值
  • D.对输入特征做标准化处理

答案:B。恒等映射指捷径路径上对输入不做任何变换,即 y = F(x) + x 中的" + x"。它保证了反向传播时梯度沿该路径乘以 1 直接回传。学习单位矩阵、限制梯度范数、特征标准化都与恒等映射的定义无关。

Q4. 关于残差网络中的梯度传播,下列描述正确的是?

单选题 · mid

  • A.梯度经恒等路径直接回传不衰减← 正确答案
  • B.梯度经捷径以乘性方式逐层放大
  • C.梯度只从残差支路传回网络
  • D.梯度在残差块内被完全阻断

答案:A。梯度走恒等捷径时导数为 1,原样回传不衰减,这是残差防消失的机制。它不是被放大,也不是只走支路或完全阻断。就像大老板的指令顺着滑梯直达底层,既不打折扣也不被放大。

Q5. 残差连接缓解梯度消失的原因包括哪些?

多选题 · mid

  • A.恒等路径的导数值为 1← 正确答案
  • B.梯度多了一条直达传输通路← 正确答案
  • C.梯度会被批量归一化操作放大
  • D.旁路的梯度贡献被系数缩放

答案:AB。残差把梯度通路变为“恒等 + 旁路”两条,恒等路径导数恒为 1,保证梯度不衰减;批量归一化是辅助手段,它的作用是稳定分布而非放大梯度;旁路梯度没有“被系数缩放”的机制。关键在于那条永不衰减的直达通路。

Q6. 当残差块输入输出维度不一致时,捷径通常如何处理?

单选题 · hard

  • A.直接截断掉多余的特征通道
  • B.用 1×1 卷积投影匹配维度← 正确答案
  • C.用池化层压缩输入的尺寸
  • D.复制输入来填充新增的通道

答案:B。维度不匹配时 ResNet 在捷径上加 1×1 卷积(必要时 stride=2)做投影,把输入变换到目标形状再相加。直接截断会丢信息,池化会改变空间尺寸但无法匹配通道数,复制填充则引入了不对齐的冗余。投影相当于给滑梯加了一个“转接器”。

Q7. ResNet-50 中 Bottleneck 块的卷积结构是?

单选题 · mid

  • A.3×3、1×1、3×3 卷积依次堆叠
  • B.1×1、3×3、1×1 卷积依次堆叠← 正确答案
  • C.1×1、1×1、3×3 卷积依次堆叠
  • D.3×3、3×3、1×1 卷积依次堆叠

答案:B。Bottleneck 是“降维(1×1)→ 计算(3×3)→ 升维(1×1)”的三明治结构:先把 256 通道压到 64,在低维做 3×3 计算,再恢复 256 通道。这样参数量约为直筒双 3×3 的 1/17。顺序错了,“缩印再放大”的意义就没了。

Q8. 关于深度网络的退化现象,下列说法正确的有哪些?

多选题 · hard

  • A.深层网络训练误差反而高于浅层网络← 正确答案
  • B.深层网络误差升高的原因是过拟合
  • C.退化现象的根源在于深层网络更难优化← 正确答案
  • D.残差结构让深网络至少不劣于浅层网络← 正确答案

答案:ACD。退化现象指 56 层网络的训练误差高于 20 层,训练误差高说明不是过拟合(过拟合时训练误差会低),根源是深层优化困难。残差通过恒等路径保证深层表达能力包含浅层,所以“至少不劣于浅层”。这正是大楼“盖高不跌倒”的保证。

Q9. ResNet 在 ILSVRC 2015 上夺冠的任务是?

单选题 · easy

  • A.目标检测任务
  • B.图像分类任务← 正确答案
  • C.图像分割任务
  • D.图像生成任务

答案:B。ResNet 以 152 层网络在图像分类任务(ImageNet 分类)上以 3.57% 的 Top-5 错误率夺冠,同时也在检测和分割任务上拿了第一。但其最核心的贡献载体是图像分类,这也是它验证残差有效性的主战场。

Q10. 残差网络在现代 AI 工业界的常见用法包括哪些?

多选题 · mid

  • A.作为骨干网络提取图像特征← 正确答案
  • B.检测分割模型普遍用残差骨干← 正确答案
  • C.预训练后迁移到新任务微调← 正确答案
  • D.替代循环网络做序列建模

答案:ABC。ResNet 最主流的工业用法是当骨干提取特征、当检测分割的 backbone、以及 ImageNet 预训练后迁移微调。它是为图像任务设计的卷积架构,虽然启发了一些序列模型设计,但“替代循环网络做序列建模”并非 ResNet 的典型用法。