共计 1882 个字符,预计需要花费 5 分钟才能阅读完成。
背景介绍:深度神经网络的梯度消失问题
当神经网络层数加深时,反向传播过程中梯度会随着链式法则逐层相乘。假设每层的梯度平均值为 0.9,经过 50 层后梯度会衰减到 0.9^50≈0.005,导致底层参数几乎无法更新。这种现象在 Sigmoid 激活函数中尤为明显,因为其导数最大值只有 0.25。
传统解决方案如 ReLU 激活函数、批归一化 (BN) 可以缓解但无法根治。2015 年 ImageNet 竞赛中,ResNet 首次让 152 层网络的训练成为可能,核心创新就是跳跃连接(skip connection)。
技术对比:传统 CNN vs ResNet
-
传统 CNN 的反向传播:
∂L/∂x = ∂L/∂y * ∂y/∂x y = f(Wx + b)梯度必须完整通过非线性变换 f()和权重矩阵 W
-
ResNet 的反向传播:
∂L/∂x = ∂L/∂y * (∂F/∂x + 1) y = F(x) + x多出的
+1项形成梯度高速公路,即使∂F/∂x 趋近 0 时仍有梯度流动
核心原理:数学推导与结构图解
残差函数设计
假设理想映射为 H(x),我们让网络学习残差 F(x) = H(x) – x。当 x 已经接近最优解时,F(x)只需逼近 0 比直接拟合 H(x)更容易:
F(x) = W2σ(W1x + b1) + b2
H(x) = F(x) + x
梯度保留机制

前向传播时,原始信号 x 与残差 F(x)相加;反向传播时,梯度可以自由选择通过残差路径或恒等路径,确保至少有一条有效传播通道。
PyTorch 实现基础残差块
import torch
import torch.nn as nn
class BasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super().__init__()
# 第一个卷积层
self.conv1 = nn.Conv2d(in_channels, out_channels,
kernel_size=3, stride=stride,
padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
# 第二个卷积层
self.conv2 = nn.Conv2d(out_channels, out_channels,
kernel_size=3, stride=1,
padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
# 跳跃连接处理维度变化
self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(in_channels, out_channels,
kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(out_channels)
)
def forward(self, x):
residual = x
out = nn.ReLU()(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(residual) # 关键跳跃连接
return nn.ReLU()(out)
实战建议
深度配置方案
- ResNet18/34:使用 BasicBlock(两层 3 ×3 卷积)
- ResNet50+:使用 Bottleneck(1×1 降维→3×3 卷积→1×1 升维)
学习率设置
- 初始学习率 0.1,每 30 个 epoch 除以 10
- 配合 Warmup:前 5 个 epoch 线性增加学习率
初始化技巧
- 卷积层:He 初始化(Kaiming Normal)
- BN 层:γ=1,β=0
- 最后一层全连接:较小权重(std=0.01)
延伸思考
Pre-activation ResNet 改进
将 BN 和 ReLU 移到卷积之前:
y = F(x) + x → y = x + F(ReLU(BN(x)))
实验显示这种结构梯度流动更顺畅,在 1000+ 层网络中仍可训练。
小型数据集应用
- 冻结部分残差块参数
- 使用更小的初始通道数(如 16→64)
- 增加 Dropout 层(p=0.2)防止过拟合
自测问题
- 为什么残差函数 F(x)=H(x)- x 比直接学习 H(x)更容易?
- 当跳跃连接两端的维度不匹配时,ResNet 如何处理?
- 假设某残差块的∂F/∂x=0.01,求该层的梯度放大系数是多少?
通过理解这些核心机制,我们可以更灵活地应用 ResNet 结构,在保持模型深度的同时避免梯度消失问题。这种设计思想也启发了后来的 DenseNet、ResNeXt 等网络架构的创新。
正文完
发表至: 未分类
近两天内
