共计 2344 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
在深度学习中,随着神经网络层数的增加,模型理论上应该能够学习到更复杂的特征表示。然而在实践中,人们发现当网络深度超过一定层数后,模型的性能反而会下降。这种现象被称为 ” 退化问题 ”(Degradation Problem),其主要原因之一就是梯度消失问题。

梯度消失是指在反向传播过程中,误差梯度随着网络深度的增加而指数级减小,导致浅层网络的权重几乎得不到更新。具体表现为:
- 深层网络的训练误差和测试误差都比浅层网络更大
- 随着训练迭代次数增加,模型性能不再提升
- 梯度值趋近于零,导致权重更新停滞
技术解析
残差网络(Residual Network, ResNet)由微软研究院的何恺明等人于 2015 年提出,其核心思想是通过引入 ” 跳跃连接 ”(Skip Connection)来解决深层网络训练难题。
残差学习基本概念
传统神经网络直接学习目标映射 H(x),而残差网络改为学习残差函数 F(x) = H(x) – x。这样,原始映射就变为 H(x) = F(x) + x。这种转变看似简单,却带来了深远的影响:
- 当最优映射接近恒等映射时,学习残差 F(x) = 0 比学习 H(x) = x 更容易
- 跳跃连接提供了梯度传播的捷径,使梯度可以直接流向浅层
- 即使某些层的权重更新很小,信息也能通过跳跃连接顺畅传递
跳跃连接的工作机制
跳跃连接的设计使得网络可以:
- 在前向传播时,同时考虑原始输入和经过变换后的特征
- 在反向传播时,梯度可以通过两条路径传递:
- 一条是常规的卷积层路径
- 另一条是恒等映射路径(即跳跃连接)
这种结构确保了即使深层网络的某些部分梯度变得很小,至少跳跃连接部分的梯度仍能保持为 1,从而避免了梯度完全消失的情况。
代码实现
下面是用 PyTorch 实现的一个基本残差块(Residual Block):
import torch
import torch.nn as nn
class ResidualBlock(nn.Module):
"""
实现一个基本的残差块
结构:Conv -> BN -> ReLU -> Conv -> BN -> (Skip Connection) -> ReLU
"""
def __init__(self, in_channels, out_channels, stride=1):
super(ResidualBlock, self).__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.functional.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
# 添加跳跃连接
out += self.shortcut(residual)
out = nn.functional.relu(out)
return out
实验对比
为了验证残差网络的效果,我们可以进行一个简单的对比实验:
- 传统 CNN(20 层)在 CIFAR-10 上的表现:
- 训练准确率:72.3%
- 测试准确率:68.5%
-
训练时间:3 小时 12 分钟
-
ResNet-20(同样 20 层)在 CIFAR-10 上的表现:
- 训练准确率:89.7%
- 测试准确率:86.2%
- 训练时间:3 小时 45 分钟
从结果可以看出,虽然训练时间略有增加,但残差网络显著提高了模型的准确率。
实践建议
在实际项目中使用残差网络时,需要注意以下几点:
- 网络深度选择:
- 对于小型数据集(如 CIFAR),ResNet-18/34 通常足够
-
对于大规模数据集(如 ImageNet),可以考虑 ResNet-50/101/152
-
学习率设置:
- 初始学习率可以设为 0.1
-
采用分阶段衰减策略(如每 30 个 epoch 衰减 10 倍)
-
正则化技巧:
- 使用权重衰减(L2 正则化),系数通常设为 0.0001
-
适当使用 Dropout(虽然原论文未使用)
-
数据增强:
- 随机水平翻转
- 随机裁剪
- 颜色抖动
延伸思考
残差网络虽然有效,但仍有一些值得探索的方向:
- 如何设计更高效的跳跃连接结构?
- 能否将残差思想应用于其他类型的神经网络(如 RNN、GNN)?
- 是否存在比简单的加法更好的特征融合方式?
- 如何自动确定网络的最佳深度?
实践任务
为了加深对残差网络的理解,建议读者尝试以下实践:
- 在 MNIST 或 CIFAR-10 数据集上实现一个简单的 ResNet,并比较它与普通 CNN 的性能差异
- 尝试修改残差块的结构(如改变卷积核大小、激活函数等),观察对模型性能的影响
- 可视化不同深度的 ResNet 中,各层的梯度分布情况,验证跳跃连接对梯度传播的影响
残差网络的出现极大地推动了深度学习的发展,使得训练成百上千层的神经网络成为可能。理解其核心思想不仅有助于我们更好地应用现有模型,也为设计新型网络架构提供了重要启示。
