想象两座城市都要盖一栋“看得远”的大楼。VGG 建筑队说:只要统一用 3×3 的小砖块,一层层老老实实往上叠,就能盖到十六七层;ResNet 建筑队也叠砖块,但他们在每一层旁边加了一部“应急电梯”——信息不用一层层爬楼梯,可以直接从楼下跳上楼上。后来大家发现:楼盖得越高,VGG 队的传话员爬到一半就没力气了,这就是梯度消失;而 ResNet 队的传话员可以乘电梯直上直下,于是 101 层、152 层照样安稳。这篇文章就用“盖楼”的比喻,带你拆解 VGG 的堆叠哲学、ResNet 的残差连接、网络退化之谜,以及这两个架构如何改变深度学习。

岗位关联

掌握这两个经典架构,你会真正理解“为什么堆得深不等于好”和“捷径为何有效”;这是面试高频题,也是你读懂 ResNet、DenseNet、Transformer 等现代模型的最小知识底座。

目录
  1. 可视化演示
  2. 演进背景:为什么两家建筑队都要盖高楼
  3. VGG堆叠设计:统一砖块盖一座深塔
  4. 深层退化之谜:楼太高为什么反而塌
  5. 残差连接原理:给每层装一部应急电梯
  6. 残差数学直觉:电梯怎么让梯度不迷路
  7. 综合对比:VGG 与 ResNet 的取舍
  8. 影响与启发:从一条捷径到整个深度学习
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示正态分布、指数分布、均匀分布的概率密度函数曲线,交互调节分布参数,可视化均值、标准差与分布形状的关系。

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

正态分布 N(μ,σ²) 蓝色曲线为概率密度函数(PDF),填充区域为概率质量 绿色线为均值μ,橙色虚线为标准差σ边界 红色点为分布峰值,紫色粒子表示采样点 f(x) = (1/σ√2π) · exp(-(x-μ)²/2σ²) 正态分布是自然界最常见的分布,由均值和标准差决定形状

演进背景:为什么两家建筑队都要盖高楼

在深度学习的早期城市里,CNN 还只是几栋矮楼。LeNet 用卷积核在像素地图上扫描,AlexNet 把楼盖到 8 层后,大家发现一个规律:楼越盖越高,看到的视野也越远——低层看到边缘,高层看到眼睛和轮胎。于是“盖高楼”成了硬道理,VGG 与 ResNet 就是在这股浪潮中登场的两支建筑队。

一栋卷积楼每一层的工作可以用一句话概括:拿着小窗口(卷积核)在上一层特征图上滑动,把窗口里的信息加权求和,再经过激活函数做一次非线性变形。写成公式就是:

VGG 和 ResNet 都认可“看得远要靠楼层多”这个方向,但对如何把楼盖稳有完全不同主张。下一节先看 VGG 的施工方案。

x(l+1)=f(W(l)∗x(l)+b(l))\mathbf{x}^{(l+1)} = f\left( W^{(l)} \ast \mathbf{x}^{(l)} + b^{(l)} \right)
这一层就像一个“标准楼层”的施工图:扫描窗口、加权求和、再做一次变形。
  1. 输入特征这是当前楼层收到的“实景照片”。
    x(l)\mathbf{x}^{(l)}
  2. 卷积核负责扫描局部模式的小窗口,对应楼层里的观察员。
    W(l)W^{(l)}
  3. 卷积运算用窗口对上一层加权求和,把邻居信息汇总起来。
    ∗\ast
  4. 非线性输出对汇总结果做一次非线性变换,让楼能表达更复杂的模式。
    f(⋅)f(\cdot)

VGG堆叠设计:统一砖块盖一座深塔

VGG 队的施工风格最像“标准砖块流水线”:不用各种大核,只认准 3×3 的小砖。每层卷积都设步幅为 1、padding 为 1,这样特征图尺寸不变;只有池化层才把图缩小一半。把二到四块砖砌成一个区块,再重复几个区块,就盖成 16 层或 19 层的大楼。

为什么只用 3×3?因为两个 3×3 卷积叠起来,等效于一个 5×5 卷积的感受野,但参数量从 25 降到 18,而且中间多一次非线性激活。换句话说,砖块越小越省料,信息还能被多加工一次。控制特征图尺寸不缩小,靠的是下面的公式:

所以 VGG 是“以简单换深度”的代表,它证明了统一小卷积核堆叠能学出很好的视觉特征。但它也把问题留给了后来者:楼真的可以无限往上盖吗?

Lout=Lin+2p−ks+1\displaystyle L_{\text{out}} = \frac{L_{\text{in}} + 2p - k}{s} + 1
VGG 把 k=3、p=1、s=1 代入后,输出尺寸刚好等于输入尺寸,楼层可以平稳地继续往上叠。
  1. 输入边长输入特征图的宽或高。
    LinL_{\text{in}}
  2. 卷积核边长卷积核的大小,VGG 中统一取 3。
    kk
  3. 填充与步幅填充 p 与步幅 s,VGG 中分别为 1 和 1。
    p,sp, s
  4. 输出边长计算后的输出特征图边长,仍然等于 L_in。
    LoutL_{\text{out}}

深层退化之谜:楼太高为什么反而塌

如果继续按 VGG 思路把楼盖到 30 层,奇怪的事情发生了:不仅测试误差下不去,连训练误差都比浅层高。这不是过拟合——过拟合是训练好但测试差,现在是训练本身就学不动。这个现象叫“退化”,它本质上是一个优化问题,不是模型容量不够。

为什么深了反而难优化?反向传播时,损失对第一层权重的梯度要从顶层一路乘回去。每乘一个小于 1 的导数,信号就缩小一点;层数一多,乘积趋近于 0,底层几乎收不到更新指令。把这条链写出来就是:

这就像传话员每下一层楼都要被扣掉三成体力,30 层后体力只剩原来的 0.7 的 30 次方,当然没力气继续训练。ResNet 就是为解决这个“体力透支”而设计了电梯。

∂L∂h1=∂L∂hL∏i=2L∂hi∂hi−1\displaystyle \frac{\partial \mathcal{L}}{\partial \mathbf{h}_1} = \frac{\partial \mathcal{L}}{\partial \mathbf{h}_L} \prod_{i=2}^{L} \frac{\partial \mathbf{h}_i}{\partial \mathbf{h}_{i-1}}
这不是某一步算错了,而是很多小于 1 的导数连乘,把信号一点点磨没了。
  1. 损失函数模型输出与真实标签之间的差距。
    L\mathcal{L}
  2. 顶层梯度损失对最后一层特征的梯度,是信号出发的起点。
    ∂L∂hL\frac{\partial \mathcal{L}}{\partial \mathbf{h}_L}
  3. 链式连乘从顶层到第一层逐层相乘,路径越长乘积越不稳定。
    ∏i=2L\prod_{i=2}^{L}
  4. 相邻层导数两层之间的传递系数,如果常小于 1,连乘后就会消失。
    ∂hi∂hi−1\frac{\partial \mathbf{h}_i}{\partial \mathbf{h}_{i-1}}

残差连接原理:给每层装一部应急电梯

ResNet 的施工方案是在每个残差块旁装一部应急电梯:输入 x 先走一段正常的卷积通道 F(x),再通过一条恒等捷径直接跳到输出端,两边做逐元素加法。于是输出不是 F 本身,而是 F(x)+x。

这样网络不需要从头学习完整映射,只需学习“还差多少”。如果卷积通道想偷懒,F(x)=0,输出仍等于 x,网络也能保住底线;当 F 学到有用信息,输出就比 x 更好。电梯的存在让前向传播和反向传播多了一条直达路线,信息可以从浅层几乎无损地冲到深层。

hi+1=F(hi,Wi)+hi\displaystyle \mathbf{h}_{i+1} = \mathcal{F}(\mathbf{h}_i, W_i) + \mathbf{h}_i
电梯不改变信息,只把原始输入原样送到楼上一层;卷积通道负责学习“还需要改变什么”。
  1. 输入特征第 i 个残差块接收到的特征图。
    hi\mathbf{h}_i
  2. 残差支路几层卷积要学习的残差函数,相当于楼层里的改造工程。
    F(hi,Wi)\mathcal{F}(\mathbf{h}_i, W_i)
  3. 恒等捷径把输入直接加到输出上,对应那部不拐弯的电梯。
    +hi+\mathbf{h}_i
  4. 输出特征同时包含“学到的变化”和“原来的信息”。
    hi+1\mathbf{h}_{i+1}

残差数学直觉:电梯怎么让梯度不迷路

为什么一条加法捷径有这么大魔力?因为求导时,加法会把"1"写进导数。对残差块求导,得到:

反向传播连乘时,这条恒等项相当于给每个楼层都装了一根完全不衰减的钢筋,把原来的“乘法链”拆成了“加法网”。这也解释了为什么 ResNet 可以上百层:不是每层都非得学到东西,学不到时电梯保证信息不丢;学到时则锦上添花。

∂hi+1∂hi=I+∂F∂hi\displaystyle \frac{\partial \mathbf{h}_{i+1}}{\partial \mathbf{h}_i} = I + \frac{\partial \mathcal{F}}{\partial \mathbf{h}_i}
哪怕残差支路的导数很小,后面还跟着一个恒等项 1,梯度永远不会被完全清零。
  1. 恒等矩阵来自恒等捷径,表示一条不打折扣的梯度通道。
    II
  2. 网络导数残差支路自身的导数,可能小于 1,也可能大于 1。
    ∂F∂hi\frac{\partial \mathcal{F}}{\partial \mathbf{h}_i}
  3. 相加结构导数由两项相加,而不是只由卷积支路决定。
    I+∂F∂hiI + \frac{\partial \mathcal{F}}{\partial \mathbf{h}_i}

综合对比:VGG 与 ResNet 的取舍

把两栋楼放在一起看:VGG 是“一砖到底”的忠实堆叠者,结构简单、范式统一、适合做特征提取骨架;ResNet 是“加电梯的革命派”,用少量额外参数换来了可训练深度。VGG-16 参数量约 1.38 亿,ResNet-50 约 0.25 亿,效果反而更好。

参数量是怎么算出来的?每一层卷积的参数等于输入通道数 × 输出通道数 × 卷积核尺寸平方:

设计哲学上,VGG 把深度当作第一性,用统一模块降低设计压力;ResNet 则意识到网络不仅要深,还要让信号传得通。两者其实不矛盾:ResNet 的残差块里依然是 3×3 卷积——VGG 的砖块没有被扔掉,而是被装进了带电梯的楼层。

P=∑lCl−1×Cl×kl2\displaystyle P = \sum_{l} C_{l-1} \times C_l \times k_l^2
小卷积核省参数,而残差连接用极少的额外参数换来了更深的可训练网络。
  1. 输入通道数第 l 层输入特征图的通道数量。
    Cl−1C_{l-1}
  2. 输出通道数第 l 层卷积核的数量,也就是输出通道数量。
    ClC_l
  3. 卷积核尺寸平方每个卷积核覆盖的空间范围。
    kl2k_l^2
  4. 逐层累加把网络中所有卷积层的参数加起来。
    ∑l\sum_{l}

影响与启发:从一条捷径到整个深度学习

残差电梯的思想很快风靡:百层以上的网络第一次变得容易训练,DenseNet 把捷径从加法变成拼接,ResNeXt 在残差块里做分组卷积,Transformer 里的残差加 LayerNorm 也沿用同一套路。可以说,今天几乎所有大模型都把残差连接当作默认配置。

多个残差块串联后,信息可以写成从浅层出发、逐层累加残差贡献的形式:

对后来者而言,最大的启发是:好的架构不是简单把层数加高,而是在关键处保留一条无损的“信息高速公路”。今天的视觉大模型和 Transformer 都从这条捷径中受益。

xL=xl+∑i=lL−1F(xi,Wi)\displaystyle \mathbf{x}_L = \mathbf{x}_l + \sum_{i=l}^{L-1} \mathcal{F}(\mathbf{x}_i, W_i)
深层特征等于浅层特征加上沿途每一层学到的变化,所以信息在每一层都有“归属感”。
  1. 浅层特征较浅层的输入特征,是电梯出发的起点。
    xl\mathbf{x}_l
  2. 深层特征经过多个残差块后的最终输出。
    xL\mathbf{x}_L
  3. 残差求和每一层残差支路的贡献都被保留并累加。
    ∑i=lL−1F(xi,Wi)\sum_{i=l}^{L-1} \mathcal{F}(\mathbf{x}_i, W_i)
  4. 加法传播反向传播时,来自每个残差项的梯度会相加,而不是连乘。
    ++

AI 应用场景

预训练视觉模型选型

阶段:特征提取与迁移学习

解决的问题:传统手工特征和浅层网络难以捕捉高精度图像语义;从零训练 VGG 又太贵。用预训练的 ResNet 相当于租一栋“带电梯的现成高楼”,只需要微调顶层就能迁移到新任务。

具体案例:商品图分类只有一万张图片,使用 ImageNet 预训练的 ResNet50 提取特征,冻结前面大部分层,只训练最后几层,准确率比从头训练 VGG 高出约 5 个百分点。

深层网络训练调优

阶段:模型训练与优化

解决的问题:深层网络训练损失不降,新手容易误以为是学习率或正则化问题,实际核心是梯度消失与退化。AI 工程师通过把普通卷积块替换成残差块,并监控梯度范数来定位问题。

具体案例:医学影像分割任务中,将 U-Net 的编码器换成 ResNet34 之后,早期 loss 从停滞变为稳定下降,验证集 Dice 系数明显提升。

已有模型的残差化升级

阶段:模型架构设计

解决的问题:已有 VGG-like 基线想提升精度,又不想推倒重来;在每两个卷积层之间加一条加法捷径,就能把普通楼层升级为残差楼层。

具体案例:工业 OCR 的 13 层 VGG 基线遇到训练瓶颈,在保留原卷积结构的基础上插入残差连接并加深到 26 层,字符识别准确率提升约 2%。

Python 演示

python28 行
import numpy as np def transfer_plain(x, weight):    return 0.5 * np.tanh(weight * x) def transfer_res(x, weight):    return x + 0.5 * np.tanh(weight * x) def plain_grad(x, layers=12, weight=0.8):    grad = 1.0    for _ in range(layers):        grad *= 0.5 * weight * (1 - np.tanh(weight * x) ** 2)        x = 0.5 * np.tanh(weight * x)    return grad def res_grad(x, layers=12, weight=0.8):    grad = 1.0    for _ in range(layers):        grad *= 1.0 + 0.5 * weight * (1 - np.tanh(weight * x) ** 2)        x = x + 0.5 * np.tanh(weight * x)    return grad if __name__ == "__main__":    x = 0.7    for n in [6, 12, 24]:        g_plain = plain_grad(x, n)        g_res = res_grad(x, n)        print("layers=%d  plain_grad=%.4f  res_grad=%.4f" % (n, g_plain, g_res))
目的:用极简的非线性层复现“普通深层网络梯度消失,残差网络梯度保持”的核心差异。
  1. grad *= 0.5 * weight * (1 - np.tanh(weight * x) ** 2)普通网络每层的梯度都要乘一个小于 1 的导数,所以层数越深,梯度越接近 0。
  2. grad *= 1.0 + 0.5 * weight * (1 - np.tanh(weight * x) ** 2)残差网络多了一个恒等项 1,即使导数很小,连乘结果也不会被清零。
  3. x = x + 0.5 * np.tanh(weight * x)模拟残差块的前向计算:输出 = 输入 + 网络层学习到的变化。
  4. for n in [6, 12, 24]分别测试 6、12、24 层,观察梯度随深度增加的变化趋势。

常见误区

误区ResNet 比 VGG 效果好,不就是因为层数更多吗?如果我把 VGG 也叠到 100 层,效果应该一样好。

正解ResNet 的关键不是“更多层”,而是残差连接让深层网络变得可训练。没有电梯的 VGG 盲目加深会出现退化,训练误差反而升高;ResNet 是用结构保证了梯度能传到底层。

为何常见:只看到论文里的层数和精度,忽略了训练动态和优化难度。

误区网络加深后测试误差变高,那肯定是过拟合了,我加 dropout 或减小模型就行了。

正解退化的特征是训练误差也升高,这是优化困难而非过拟合。加 dropout 解决不了梯度连乘消失的问题,应该改善梯度传递,比如换残差结构。

为何常见:把“测试误差高”和“过拟合”划等号,没有先看训练误差。

误区残差连接就是把输入和卷积输出拼在一起,让通道数变多。

正解ResNet 默认是逐元素相加,要求输入与输出形状相同;通道拼接是 DenseNet 的做法。加法捷径不会增加通道数,因此几乎不引入额外参数。

为何常见:听说 skip connection 就以为是拼接,混淆了 ResNet 和 DenseNet 的跨层设计。

误区VGG 用 3×3 只是把卷积核改小,和 5×5 差不多,没什么技术含量。

正解两个 3×3 堆叠的感受野等效于一个 5×5,但参数量更少、非线性更多。VGG 用这种统一小核证明了“小砖块加大深度”既能省参数又能提升表达力。

为何常见:只看到了感受野相同,忽视了参数效率和非线性次数。

误区只要加了残差连接,梯度就永远不会消失,学习率随便设大一点也没关系。

正解残差提供了恒等通道,但残差支路的导数仍可能变大,极端深层或初始化不当时仍会出现梯度爆炸或振荡。实际工程中还要配合 BatchNorm、合适初始化与学习率策略。

为何常见:把“缓解”理解成了“彻底解决”,忽略了非线性层和权重的相互作用。

面试题

Q1. VGG 网络最突出的结构特点是?

单选题 · easy

  • A.只用 3x3 小卷积核并堆叠很多层← 正确答案
  • B.只用 5x5 卷积核并减少网络层数
  • C.用全连接层直接分类而非卷积
  • D.用循环连接让特征反复迭代

答案:A。VGG 的核心设计就是用统一 3x3 卷积堆叠深度。其他选项分别改为大核、全连接、循环,都不符合 VGG 的卷积堆叠思路。

Q2. 两个 3x3 卷积堆叠,感受野相当于?

单选题 · easy

  • A.一个 5x5 卷积的感受野大小← 正确答案
  • B.一个 7x7 卷积的感受野大小
  • C.一个 3x3 卷积的感受野大小
  • D.一个 9x9 卷积的感受野大小

答案:A。两个 3x3 卷积叠加覆盖的区域相当于一个 5x5 卷积,但参数量更少,中间还多一次非线性激活。

Q3. VGG 中 3x3 卷积 stride=1 且 padding=1 的效果是?

单选题 · easy

  • A.保持特征图宽高不缩小← 正确答案
  • B.让特征图宽高扩大一倍
  • C.让特征图宽高缩小一半
  • D.把特征图所有值变成零

答案:A。代入尺寸公式 (L+2p-k)/s+1,当 k=3、p=1、s=1 时输出尺寸等于输入尺寸,所以特征图宽高不缩小。

Q4. 网络退化现象最典型的证据是?

单选题 · mid

  • A.更深网络训练误差反而升高← 正确答案
  • B.更深网络测试误差突然降低
  • C.浅层网络完全无法收敛
  • D.卷积核参数全部变为负数

答案:A。退化现象是深层网络训练误差也高于浅层网络,属于优化困难,而不是过拟合,也不是参数符号问题。

Q5. ResNet 残差块的输出计算是?

单选题 · mid

  • A.输出 = 卷积结果 + 恒等输入← 正确答案
  • B.输出 = 卷积结果 * 恒等输入
  • C.输出 = 卷积结果拼接恒等输入
  • D.输出 = 卷积结果 - 恒等输入

答案:A。残差块是 y=F(x)+x,加法代表恒等捷径;乘法、拼接、相减都不是 ResNet 的标准做法。

Q6. 关于残差连接缓解梯度消失,下列说法正确的有?

多选题 · mid

  • A.导数中会出现恒等项 1 的通道← 正确答案
  • B.恒等项帮助梯度跨层直传← 正确答案
  • C.残差连接完全消除梯度所有问题
  • D.残差连接把乘法链变成加法网← 正确答案

答案:ABD。残差让导数变成 1+∂F/∂x,梯度多了一条直传通道,训练也由连乘主导变成多路径相加。但残差不能完全消除训练不稳定,C 说法太绝对。

Q7. 当残差块希望实现恒等映射时,网络可以学习到?

单选题 · hard

  • A.让卷积支路的输出趋近于 0← 正确答案
  • B.让卷积支路的输出趋近于 1
  • C.让恒等捷径的权重趋近于 0
  • D.让激活函数输出全部等于 0

答案:A。如果最优映射是恒等映射,残差结构只需让 F(x) 趋近于 0,输出就接近 x;而不是修改捷径或激活。

Q8. 关于 VGG 与 ResNet 的参数效率,正确说法是?

单选题 · hard

  • A.ResNet 用较少参数达到更低错误← 正确答案
  • B.VGG 用较少参数达到更低错误
  • C.ResNet 参数量是 VGG 的十倍以上
  • D.两者参数量和效果完全一样

答案:A。ResNet-50 参数约 25M,VGG-16 参数约 138M,且 ResNet 在 ImageNet 上错误率更低,说明其参数效率更高。

Q9. 以下关于退化现象的说法,正确的有?

多选题 · mid

  • A.深层模型训练误差可能高于浅层← 正确答案
  • B.退化主要由梯度传递困难造成← 正确答案
  • C.退化等同于过拟合现象
  • D.残差连接能帮助缓解该问题← 正确答案

答案:ABD。退化的核心是深层优化困难,梯度连乘容易消失,训练误差不降;这不是过拟合,残差连接通过恒等捷径可以有效缓解。

Q10. 残差连接在后续深度学习中的影响包括?

多选题 · hard

  • A.让百层以上网络更容易训练← 正确答案
  • B.启发了 DenseNet 等跨层设计← 正确答案
  • C.证明卷积核必须使用 7x7
  • D.成为 Transformer 中的常见组件← 正确答案

答案:ABD。残差让超深网络成为可能,DenseNet 等架构沿用了跨层连接思想,Transformer 也普遍使用残差加 LayerNorm;但它没有证明卷积核必须用 7x7。