ResNet(Residual Network,残差网络)是由何恺明等人于2015年提出的深度卷积神经网络架构,在ImageNet比赛中取得了冠军,并因其极深的网络结构(如152层)和有效的训练方法而闻名。ResNet的核心创新是残差连接(也称为跳跃连接),它有效解决了深层神经网络训练中的退化问题,使得训练上百层甚至上千层的网络成为可能。

1. 背景:深度网络的退化问题

理论上,随着网络层数增加,模型的表达能力应该更强,性能也应该更好。然而,实验发现,当网络层数加深到一定程度时,训练集上的准确率会饱和甚至下降,这种现象被称为“退化问题”。注意这不是过拟合(过拟合时训练准确率仍很高,但测试准确率下降),而是网络自身难以优化,导致更深的网络反而产生更高的训练误差。

退化问题表明,简单的堆叠层数并不能直接提升性能,因为深层网络难以学习到恒等映射(identity mapping)——即如果增加的层不能带来更好的性能,至少应该保持当前水平,但实际中优化算法难以做到这一点。

2. 核心思想:残差学习

ResNet的作者提出,与其让网络直接学习期望的潜在映射 H ( x ) H(x) H(x),不如学习残差 F ( x ) = H ( x ) − x F(x) = H(x) - x F(x)=H(x)x。这样,原始映射就变成了 H ( x ) = F ( x ) + x H(x) = F(x) + x H(x)=F(x)+x。如果恒等映射是最优的(即增加层不改变结果),那么学习残差 F ( x ) F(x) F(x) 只需要趋近于0即可,这比直接学习恒等映射更容易。

在数学上,残差块的形式为:
y = F ( x , { W i } ) + x y = F(x, \{W_i\}) + x y=F(x,{Wi})+x
其中 x x x 是输入, y y y 是输出, F ( x , { W i } ) F(x, \{W_i\}) F(x,{Wi}) 是要学习的残差映射(通常包含卷积、批归一化、激活函数等)。如果 F F F x x x 的维度不同,可以通过一个线性投影 W s W_s Ws 来匹配维度:
y = F ( x , { W i } ) + W s x y = F(x, \{W_i\}) + W_s x y=F(x,{Wi})+Wsx

3. 残差块的结构

一个典型的残差块(用于ResNet-34等)如下:

  • 输入 x x x
  • 经过第一个卷积层(如3×3卷积),批归一化,ReLU激活
  • 经过第二个卷积层(如3×3卷积),批归一化
  • 将第二个卷积层的输出与输入 x x x 相加(跳跃连接)
  • 再通过ReLU激活

如果输入和输出的通道数或尺寸发生变化(例如通过步长为2的卷积降采样),跳跃连接上需要添加一个1×1卷积来调整维度。

对于更深的ResNet(如ResNet-50/101/152),通常使用“瓶颈”结构:1×1卷积降维 → 3×3卷积 → 1×1卷积升维。这样可以在减少计算量的同时保持性能。

4. 为什么ResNet有效?

  • 梯度流动更顺畅:在反向传播时,梯度可以通过跳跃连接直接传到前面的层,避免了梯度消失问题。因为恒等映射的导数恒为1,所以即使层数很深,梯度也能有效回传。
  • 学习恒等映射更容易:如果网络需要恒等映射,残差块只需将残差部分学习为0即可,这比通过堆叠非线性层拟合恒等映射容易得多。
  • 网络退化问题的缓解:由于跳跃连接的存在,深层网络至少不会比浅层网络差,因为它可以简单复制浅层网络的映射,而让新增层学习残差。

5. 数值实例

为了直观理解,我们考虑一个简单的残差块,其中没有激活函数(或假设线性),以便计算。

假设输入 x = 5 x = 5 x=5,期望输出 H ( x ) = 5.1 H(x) = 5.1 H(x)=5.1。如果不使用残差,网络需要直接学习 H ( x ) = 5.1 H(x) = 5.1 H(x)=5.1。使用残差后,网络需要学习 F ( x ) = H ( x ) − x = 0.1 F(x) = H(x) - x = 0.1 F(x)=H(x)x=0.1。假设网络的权重初始化导致输出接近0,那么加上跳跃连接后输出接近5,稍微调整权重就能达到5.1。相比之下,直接学习5.1需要从0或随机值开始,更难优化。

再看一个实际训练中的例子(简化版):

假设有一个两层网络(无跳跃连接),输入 x x x,第一层权重 w 1 w_1 w1,第二层权重 w 2 w_2 w2,输出 y ^ = w 2 ( w 1 x ) \hat{y} = w_2 (w_1 x) y^=w2(w1x)。目标输出 y y y。梯度计算中, ∂ L / ∂ w 1 = ∂ L / ∂ y ^ ⋅ w 2 ⋅ x \partial L / \partial w_1 = \partial L / \partial \hat{y} \cdot w_2 \cdot x L/w1=L/y^w2x。如果 w 2 w_2 w2 很小,梯度也会很小,导致第一层更新缓慢。

如果加上跳跃连接: y ^ = w 2 ( w 1 x ) + x \hat{y} = w_2 (w_1 x) + x y^=w2(w1x)+x。此时梯度 ∂ L / ∂ w 1 = ∂ L / ∂ y ^ ⋅ w 2 ⋅ x \partial L / \partial w_1 = \partial L / \partial \hat{y} \cdot w_2 \cdot x L/w1=L/y^w2x 不变,但 ∂ L / ∂ x \partial L / \partial x L/x 包含直接来自跳跃连接的项(值为1),使得梯度更容易流向前层。虽然这个例子不完美(因为跳跃连接直接跨过两层),但说明了跳跃连接有助于梯度传播。

更具体的数值实例可以模拟前向和反向:

假设一个残差块: y = ReLU ( Conv 2 ( ReLU ( Conv 1 ( x ) ) ) + x ) y = \text{ReLU}( \text{Conv}_2(\text{ReLU}(\text{Conv}_1(x))) + x ) y=ReLU(Conv2(ReLU(Conv1(x)))+x)。给定输入 x = [ 1 , − 1 ] x = [1, -1] x=[1,1](简单向量),Conv1和Conv2是线性变换(比如用单位矩阵,偏置为0)。那么:

  • Conv1(x) = x = [1, -1]
  • ReLU后 = [1, 0]
  • Conv2([1,0]) = [1,0]
  • 与x相加: [1,0] + [1,-1] = [2,-1]
  • 最终ReLU: [2,0]

可以看到,负值被跳跃连接保留了一部分(-1),最终经过ReLU变成0,但如果是普通网络(无跳跃),负值可能直接丢失信息。跳跃连接有助于保留原始信息。

6. 生活实例理解

我们可以用几个生活实例来类比残差连接:

  • 搭积木:想象你要搭建一个很高的积木塔。普通网络就像把积木直接往上堆,如果某块积木放歪了,上面的都会歪,而且很难调整。残差网络就像给每层积木都加了“支撑柱”(跳跃连接),即使某层有点歪,支撑柱也能把力直接传到下面,保证整体稳定。这样你可以放心地搭建更高的塔。
  • 接力赛跑:在接力赛中,每一棒选手都要跑一段距离。如果某个选手跑得不好,后面的选手必须从他接力的位置继续跑,这可能导致整体成绩下降(类似梯度消失)。残差连接相当于在每个接力点,选手可以直接从起点(或前几个点)获得一个“辅助动力”,使得即使某个选手跑得慢,整体速度也不会受太大影响。
  • 记笔记:你在学习一门新知识(比如深度学习),你会先记住一些基础概念(输入 x x x)。然后学习新的细节(残差 F ( x ) F(x) F(x)),最后把新知识和原有知识结合起来( x + F ( x ) x + F(x) x+F(x))。如果新知识很难理解,你可以直接依赖原有知识,而新知识只负责补充微小差异。这样即使新知识没学好,你也不会完全不懂。
  • 电梯与楼梯:想象你要从1楼到10楼。普通网络像爬楼梯,每层必须经过(梯度要逐层传播)。残差网络像同时有电梯和楼梯:你可以坐电梯直达某些楼层(跳跃连接),也可以走楼梯(卷积层),这样更灵活,不容易累(梯度消失)。

附:深度网络的退化问题(Degradation Problem)

1. 什么是退化问题?

在深度神经网络中,退化问题指的是:随着网络层数的增加,模型在训练集上的准确率达到饱和后,反而出现迅速下降的现象。这种下降并非由过拟合导致(过拟合时训练准确率仍很高,只是测试准确率下降),而是由于深层网络难以优化,导致训练误差升高。

典型现象(来自ResNet论文的实验):

  • 在CIFAR-10数据集上,一个20层的普通网络(plain network)训练误差较低;
  • 而一个56层的普通网络,训练误差反而比20层网络更高,测试误差也更高。
    这表明,单纯增加层数并不能自动提升性能,反而可能损害优化效果。

2. 退化问题的原因

退化问题的本质是优化困难。深层网络在反向传播时,梯度需要从输出层逐层传递回输入层,容易出现梯度消失梯度爆炸,导致靠近输入的层更新缓慢。即使采用合适的初始化(如He初始化)和归一化(如批归一化)来缓解梯度消失,深层网络依然难以拟合恒等映射。换句话说,当网络需要学习一个从输入到输出的恒等映射时(即新增的层什么也不做),堆叠的非线性层很难直接将权重逼近0,从而破坏了原有的性能。

从数学上看,假设一个深层网络由多个非线性层堆叠而成,期望的映射为 H ( x ) H(x) H(x)。如果最优解恰好是恒等映射(即 H ( x ) = x H(x)=x H(x)=x),那么网络需要将每一层的参数调整到使输出等于输入。但非线性层(如ReLU、卷积)的组合很难精确实现恒等映射,导致训练误差不降反升。

3. 数值计算实例

为了直观理解退化问题,我们设计一个极简的神经网络,并用数值模拟其训练过程。考虑以下任务:

  • 输入:单个标量 x = 1 x = 1 x=1
  • 目标输出 y = 0.5 y = 0.5 y=0.5(常数)
  • 网络结构:分别构建一个单层网络和一个三层网络,每层只有一个神经元,激活函数为 Sigmoid(因其易饱和,能体现梯度消失)。
  • 损失函数:均方误差 L = ( 输出 − 0.5 ) 2 L = (输出 - 0.5)^2 L=(输出0.5)2
  • 初始化:所有权重初始化为 1 1 1,偏置为0(简化计算)。

3.1 单层网络

  • 网络表达式: o u t p u t = σ ( w ⋅ x ) output = \sigma(w \cdot x) output=σ(wx),其中 σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1+e^{-z}} σ(z)=1+ez1
  • 前向传播: w = 1 w=1 w=1 z = 1 × 1 = 1 z = 1 \times 1 = 1 z=1×1=1 o u t p u t = σ ( 1 ) ≈ 0.7310585786 output = \sigma(1) \approx 0.7310585786 output=σ(1)0.7310585786
  • 损失: L = ( 0.7310585786 − 0.5 ) 2 = ( 0.2310585786 ) 2 ≈ 0.053388 L = (0.7310585786 - 0.5)^2 = (0.2310585786)^2 \approx 0.053388 L=(0.73105857860.5)2=(0.2310585786)20.053388
  • 梯度计算:
    • ∂ L ∂ o u t p u t = 2 ( o u t p u t − 0.5 ) = 2 × 0.2310585786 = 0.4621171572 \frac{\partial L}{\partial output} = 2(output - 0.5) = 2 \times 0.2310585786 = 0.4621171572 outputL=2(output0.5)=2×0.2310585786=0.4621171572
    • ∂ o u t p u t ∂ z = σ ( z ) ( 1 − σ ( z ) ) = 0.7310585786 × ( 1 − 0.7310585786 ) = 0.7310585786 × 0.2689414214 ≈ 0.196611933 \frac{\partial output}{\partial z} = \sigma(z)(1-\sigma(z)) = 0.7310585786 \times (1-0.7310585786) = 0.7310585786 \times 0.2689414214 \approx 0.196611933 zoutput=σ(z)(1σ(z))=0.7310585786×(10.7310585786)=0.7310585786×0.26894142140.196611933
    • ∂ z ∂ w = x = 1 \frac{\partial z}{\partial w} = x = 1 wz=x=1
    • 所以 ∂ L ∂ w = 0.4621171572 × 0.196611933 × 1 ≈ 0.090844 \frac{\partial L}{\partial w} = 0.4621171572 \times 0.196611933 \times 1 \approx 0.090844 wL=0.4621171572×0.196611933×10.090844
  • 梯度下降更新(学习率 η = 0.5 \eta = 0.5 η=0.5): w n e w = 1 − 0.5 × 0.090844 = 0.954578 w_{new} = 1 - 0.5 \times 0.090844 = 0.954578 wnew=10.5×0.090844=0.954578
  • 一次更新后,新的输出约为 σ ( 0.954578 ) ≈ 0.722 \sigma(0.954578) \approx 0.722 σ(0.954578)0.722,损失降至约0.049。可见单层网络能快速降低损失。

3.2 三层网络

网络结构: x → 神经元1 → 神经元2 → 神经元3 → o u t p u t x \rightarrow \text{神经元1} \rightarrow \text{神经元2} \rightarrow \text{神经元3} \rightarrow output x神经元1神经元2神经元3output

  • 每层参数: w 1 , w 2 , w 3 w_1, w_2, w_3 w1,w2,w3(均为标量),偏置为0。
  • 前向传播(初始化 w 1 = w 2 = w 3 = 1 w_1=w_2=w_3=1 w1=w2=w3=1):
    • a 1 = σ ( w 1 x ) = σ ( 1 ) ≈ 0.7310585786 a_1 = \sigma(w_1 x) = \sigma(1) \approx 0.7310585786 a1=σ(w1x)=σ(1)0.7310585786
    • a 2 = σ ( w 2 a 1 ) = σ ( 1 × 0.7310585786 ) = σ ( 0.7310585786 ) a_2 = \sigma(w_2 a_1) = \sigma(1 \times 0.7310585786) = \sigma(0.7310585786) a2=σ(w2a1)=σ(1×0.7310585786)=σ(0.7310585786)
      • 计算 z 2 = 0.7310585786 z_2 = 0.7310585786 z2=0.7310585786 σ ( z 2 ) = 1 1 + e − 0.7310585786 ≈ 0.674534 \sigma(z_2) = \frac{1}{1+e^{-0.7310585786}} \approx 0.674534 σ(z2)=1+e0.731058578610.674534
    • a 3 = σ ( w 3 a 2 ) = σ ( 1 × 0.674534 ) = σ ( 0.674534 ) ≈ 0.662407 a_3 = \sigma(w_3 a_2) = \sigma(1 \times 0.674534) = \sigma(0.674534) \approx 0.662407 a3=σ(w3a2)=σ(1×0.674534)=σ(0.674534)0.662407
    • 输出 y ^ = a 3 ≈ 0.662407 \hat{y} = a_3 \approx 0.662407 y^=a30.662407
  • 损失: L = ( 0.662407 − 0.5 ) 2 = ( 0.162407 ) 2 ≈ 0.026376 L = (0.662407 - 0.5)^2 = (0.162407)^2 \approx 0.026376 L=(0.6624070.5)2=(0.162407)20.026376

此时损失0.0264,比单层网络的初始损失0.0534小?注意:这是初始值,三层网络初始输出更接近0.5是因为sigmoid的堆叠使输出趋向中间值。但退化问题关注的是训练过程中能否继续优化到更低的损失,以及最终收敛时的损失。

我们计算反向传播,观察梯度大小(是否衰减):

首先计算输出层梯度:

  • ∂ L ∂ y ^ = 2 ( y ^ − 0.5 ) = 2 × 0.162407 = 0.324814 \frac{\partial L}{\partial \hat{y}} = 2(\hat{y} - 0.5) = 2 \times 0.162407 = 0.324814 y^L=2(y^0.5)=2×0.162407=0.324814
  • 对于第三层: ∂ y ^ ∂ z 3 = σ ( z 3 ) ( 1 − σ ( z 3 ) ) \frac{\partial \hat{y}}{\partial z_3} = \sigma(z_3)(1-\sigma(z_3)) z3y^=σ(z3)(1σ(z3)),其中 z 3 = w 3 a 2 = 1 × 0.674534 = 0.674534 z_3 = w_3 a_2 = 1 \times 0.674534 = 0.674534 z3=w3a2=1×0.674534=0.674534
    • σ ( z 3 ) ≈ 0.662407 \sigma(z_3) \approx 0.662407 σ(z3)0.662407,所以导数 ≈ 0.662407 × ( 1 − 0.662407 ) = 0.662407 × 0.337593 ≈ 0.22365 \approx 0.662407 \times (1-0.662407) = 0.662407 \times 0.337593 \approx 0.22365 0.662407×(10.662407)=0.662407×0.3375930.22365
    • ∂ L ∂ w 3 = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ z 3 ⋅ a 2 = 0.324814 × 0.22365 × 0.674534 ≈ 0.324814 × 0.15086 ≈ 0.0490 \frac{\partial L}{\partial w_3} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z_3} \cdot a_2 = 0.324814 \times 0.22365 \times 0.674534 \approx 0.324814 \times 0.15086 \approx 0.0490 w3L=y^Lz3y^a2=0.324814×0.22365×0.6745340.324814×0.150860.0490

第二层:

  • ∂ L ∂ a 2 = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ z 3 ⋅ w 3 = 0.324814 × 0.22365 × 1 ≈ 0.07266 \frac{\partial L}{\partial a_2} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z_3} \cdot w_3 = 0.324814 \times 0.22365 \times 1 \approx 0.07266 a2L=y^Lz3y^w3=0.324814×0.22365×10.07266
  • z 2 = w 2 a 1 = 1 × 0.7310585786 = 0.7310585786 z_2 = w_2 a_1 = 1 \times 0.7310585786 = 0.7310585786 z2=w2a1=1×0.7310585786=0.7310585786 a 2 = σ ( z 2 ) ≈ 0.674534 a_2 = \sigma(z_2) \approx 0.674534 a2=σ(z2)0.674534,导数 ≈ 0.674534 × ( 1 − 0.674534 ) = 0.674534 × 0.325466 ≈ 0.2195 \approx 0.674534 \times (1-0.674534) = 0.674534 \times 0.325466 \approx 0.2195 0.674534×(10.674534)=0.674534×0.3254660.2195
  • ∂ L ∂ w 2 = ∂ L ∂ a 2 ⋅ ∂ a 2 ∂ z 2 ⋅ a 1 = 0.07266 × 0.2195 × 0.7310585786 ≈ 0.07266 × 0.1604 ≈ 0.01166 \frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial a_2} \cdot \frac{\partial a_2}{\partial z_2} \cdot a_1 = 0.07266 \times 0.2195 \times 0.7310585786 \approx 0.07266 \times 0.1604 \approx 0.01166 w2L=a2Lz2a2a1=0.07266×0.2195×0.73105857860.07266×0.16040.01166

第一层:

  • ∂ L ∂ a 1 = ∂ L ∂ a 2 ⋅ ∂ a 2 ∂ z 2 ⋅ w 2 = 0.07266 × 0.2195 × 1 ≈ 0.01595 \frac{\partial L}{\partial a_1} = \frac{\partial L}{\partial a_2} \cdot \frac{\partial a_2}{\partial z_2} \cdot w_2 = 0.07266 \times 0.2195 \times 1 \approx 0.01595 a1L=a2Lz2a2w2=0.07266×0.2195×10.01595
  • z 1 = w 1 x = 1 z_1 = w_1 x = 1 z1=w1x=1 a 1 = σ ( 1 ) ≈ 0.7310585786 a_1 = \sigma(1) \approx 0.7310585786 a1=σ(1)0.7310585786,导数 ≈ 0.196612 \approx 0.196612 0.196612
  • ∂ L ∂ w 1 = ∂ L ∂ a 1 ⋅ ∂ a 1 ∂ z 1 ⋅ x = 0.01595 × 0.196612 × 1 ≈ 0.003136 \frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial a_1} \cdot \frac{\partial a_1}{\partial z_1} \cdot x = 0.01595 \times 0.196612 \times 1 \approx 0.003136 w1L=a1Lz1a1x=0.01595×0.196612×10.003136

可见,从第三层到第一层,梯度从 0.0490 0.0490 0.0490 衰减到 0.0031 0.0031 0.0031,衰减了约15倍。使用学习率 η = 0.5 \eta=0.5 η=0.5 更新:

  • w 3 w_3 w3 更新: 1 − 0.5 × 0.0490 = 0.9755 1 - 0.5 \times 0.0490 = 0.9755 10.5×0.0490=0.9755
  • w 2 w_2 w2 更新: 1 − 0.5 × 0.01166 = 0.99417 1 - 0.5 \times 0.01166 = 0.99417 10.5×0.01166=0.99417
  • w 1 w_1 w1 更新: 1 − 0.5 × 0.003136 = 0.998432 1 - 0.5 \times 0.003136 = 0.998432 10.5×0.003136=0.998432

第一层权重几乎没变,而第三层变化稍大。再进行一次前向传播(近似):

  • a 1 = σ ( 0.998432 × 1 ) ≈ σ ( 0.998432 ) ≈ 0.7308 a_1 = \sigma(0.998432 \times 1) \approx \sigma(0.998432) \approx 0.7308 a1=σ(0.998432×1)σ(0.998432)0.7308(变化很小)
  • a 2 = σ ( 0.99417 × 0.7308 ) ≈ σ ( 0.7265 ) ≈ 0.674 a_2 = \sigma(0.99417 \times 0.7308) \approx \sigma(0.7265) \approx 0.674 a2=σ(0.99417×0.7308)σ(0.7265)0.674(几乎不变)
  • a 3 = σ ( 0.9755 × 0.674 ) ≈ σ ( 0.6574 ) ≈ 0.658 a_3 = \sigma(0.9755 \times 0.674) \approx \sigma(0.6574) \approx 0.658 a3=σ(0.9755×0.674)σ(0.6574)0.658(输出略有下降)
  • 损失约为 ( 0.658 − 0.5 ) 2 = 0.158 2 = 0.0250 (0.658-0.5)^2 = 0.158^2 = 0.0250 (0.6580.5)2=0.1582=0.0250,仅下降了一点。

若继续训练,由于第一层更新极慢,整体收敛会非常缓慢。相比之下,单层网络一次更新损失就从0.0534降到0.049,效率高得多。如果训练相同步数,三层网络的损失可能仍高于单层网络能达到的更低损失(单层网络经过多次更新可以逼近0.5)。这就模拟了退化现象:深层网络因梯度衰减导致优化困难,训练误差下降缓慢,最终可能陷入局部最优,达不到与浅层网络相当的训练精度

3.3 引入残差连接的效果

如果我们在三层网络中加入跳跃连接,比如将输入直接加到第三层的输出上(假设维度匹配),那么前向传播变为:
y ^ = a 3 + x \hat{y} = a_3 + x y^=a3+x
但这里 a 3 a_3 a3 是sigmoid输出,范围(0,1),加上x=1后范围(1,2),与目标0.5不符,需要调整。更合理的残差块通常是在激活之前相加。为了简单,我们考虑一个线性残差块: y ^ = a 3 + x \hat{y} = a_3 + x y^=a3+x,同时将目标改为1.5(使期望输出1.5,这样残差学习更容易)。但这个改动会偏离原问题。不过,我们可以直接说明,在残差网络中,跳跃连接使得梯度可以直接回传到前面层,避免衰减。例如,在反向传播中,损失对输入的导数会包含来自跳跃连接的常数1,从而缓解梯度消失。

4. 总结

退化问题揭示了深层网络优化中的固有困难,而ResNet通过残差连接巧妙地绕过了这一障碍。数值实例表明,普通深层网络由于梯度逐层衰减,靠近输入的层更新缓慢,导致训练误差难以降低。而残差连接为梯度提供了“高速公路”,使网络更容易学习恒等映射或微小变化,从而保证了深层网络的性能不低于浅层网络。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐