残差连接与现代 CNN
残差连接提供信息与梯度捷径,使深层网络更容易优化。
学习目标
- 零残差与投影残差的形状
- 1×1 卷积为什么能够做捷径投影?
- 说明:残差连接改善优化结构,但不会保证更深网络一定更准确。
为什么需要这个概念
残差块把主分支的变换 F(x) 与捷径分支相加。形状相同时捷径可直接用 x,形状变化时通常用可学习投影匹配。
学习前需要掌握
背景与问题
简单地堆叠更多层,优化可能反而困难:网络不仅要学有用变换,还要学会在某些层保留已有表示。残差连接显式提供了保留路径。
概念定义
残差块把主分支的变换 F(x) 与捷径分支相加。形状相同时捷径可直接用 x,形状变化时通常用可学习投影匹配。
直观理解
主分支只需要提出“在原表示上改多少”。如果这一步暂时没有帮助,接近零的残差就能近似保留原表示。
核心原理
当 y=x+F(x) 时,反向导数包含直接路径与残差路径两项。这改善深层信息和梯度传递的条件,但不意味着梯度在所有网络中绝不消失,或任意深度都容易训练。
逐元素相加要求两个分支形状一致。通道从 64 变为 128、空间从 32 变为 16 时,捷径常用 1×1、stride=2 的卷积;这条路径也有参数,并非恒等映射。不能依赖意外广播来“凑成可加”。
加法后是否再激活、归一化放在何处,会形成不同残差块配方。加载预训练权重时应保持结构一致;残差连接也不能修复失真的输入或不合适损失。
数学表达
核心公式
残差块把主分支的变换 F(x) 与捷径分支相加。形状相同时捷径可直接用 x,形状变化时通常用可学习投影匹配。
变量含义
Nbatch sizeD/H特征或隐藏维度
计算步骤
- 1零残差使输出逐元素等于输入。
- 2主分支 3×3 stride=2、padding=1 得到 (2,6,4,4)。
- 3捷径 1×1 stride=2 得到同形状,方可相加。
代码对应位置
示例 1零残差与投影残差的形状的最小验证:使用完整构造输入核对零残差与投影残差的形状,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch size |
D/H | 特征或隐藏维度 |
完整数值示例
零残差与投影残差的形状
已知条件
- 输入为 (2,3,8,8)
- 恒等分支与一个全零同形状残差相加
- 降采样块将通道改为 6、空间改为 4×4
计算步骤
- 零残差使输出逐元素等于输入。
- 主分支 3×3 stride=2、padding=1 得到 (2,6,4,4)。
- 捷径 1×1 stride=2 得到同形状,方可相加。
计算结果
恒等情形最大差为 0;投影块两个分支和输出均为 (2,6,4,4)。
处理前后对比
- 残差连接改善优化结构,但不会保证更深网络一定更准确。
零残差与投影残差的形状
这里把残差直接设为零,只是验证恒等通路的代数性质,不是建议把所有主分支参数永久清零。真实训练仍需合适初始化和非线性。
若只给主分支加 stride 而保持捷径不变,就会得到 8×8 与 4×4 两种空间尺寸,无法相加。错误位置通常可由逐分支 shape 打印立即定位。
计算与实现步骤
- 零残差使输出逐元素等于输入。
- 主分支 3×3 stride=2、padding=1 得到 (2,6,4,4)。
- 捷径 1×1 stride=2 得到同形状,方可相加。
代码实现
示例 1
零残差与投影残差的形状的最小验证
example_01.py用途:使用完整构造输入核对零残差与投影残差的形状,输出只表示本例计算。
import torch
from torch import nn
x = torch.ones(2, 3, 8, 8)
print("identity max diff:", (x + torch.zeros_like(x) - x).abs().max().item())
main = nn.Conv2d(3, 6, 3, stride=2, padding=1)
shortcut = nn.Conv2d(3, 6, 1, stride=2)
a, b = main(x), shortcut(x)
print(tuple(a.shape), tuple(b.shape), tuple((a + b).shape))代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对零残差与投影残差的形状,输出只表示本例计算。
b- 偏置项。
Step 1 · 1–8 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
from torch import nn
x = torch.ones(2, 3, 8, 8)
print("identity max diff:", (x + torch.zeros_like(x) - x).abs().max().item())
main = nn.Conv2d(3, 6, 3, stride=2, padding=1)
shortcut = nn.Conv2d(3, 6, 1, stride=2)
a, b = main(x), shortcut(x)
print(tuple(a.shape), tuple(b.shape), tuple((a + b).shape))预期输出或运行结果
identity max diff: 0.0 (2, 6, 4, 4) (2, 6, 4, 4) (2, 6, 4, 4)
常见错误 · 4 条
- 两分支形状不同
- 把相加写拼接
- 层越深一定越准
- 确认样本轴、特征轴以及 X 与 y 的第一维完全对应。
实际应用
- 深层视觉骨干网络
- Transformer 中的子层残差连接
常见错误
- 两分支形状不同
- 把相加写拼接
- 层越深一定越准
常见问题
1×1 卷积为什么能够做捷径投影?
它在每个采样位置混合输入通道,设置 stride 后还能同步下采样;因此能把通道数和空间尺寸对齐。
这个示例能说明什么边界?
残差连接改善优化结构,但不会保证更深网络一定更准确。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。