结构笔记 / 6 分钟
ResNet:identity 留下了什么
用 out += identity 阅读残差连接,而不是把它当成性能承诺。先找到那条没有绕路的路径
残差网络常被概括成“可以训练更深的网络”,但阅读实现时,更可靠的起点是下面三行:
identity = x
out = block(x)
out += identity
主分支计算 F(x),identity 路径保留输入 x。两条路径汇合后得到 F(x) + x。这解释了数据在一个残差块里怎样流动,比先接受某个性能结论更具体。
相加比拼接多一个限制
Inception 常沿通道维拼接,ResNet 在这里做逐元素相加。逐元素相加要求两侧形状完全一致:批次、通道、高度和宽度都不能不同。
因此,阅读残差块时我会同时追踪两条路径:
main path: x -> conv -> norm -> activation -> conv
identity path: x -> unchanged, or projection
merge: main + identity
只看主分支容易漏掉真正的形状冲突。
尺寸变化时需要投影
当主分支使用 stride 缩小特征图,或改变输出通道数时,原始 x 不能直接相加。常见处理是在 identity 路径加入 1x1 卷积,并使用相同 stride:
if self.downsample is not None:
identity = self.downsample(x)
out += identity
这个分支不是装饰。它负责把 identity 转换成与主分支相同的形状。
用断言替代猜测
调试残差块时,可以在相加前明确检查形状:
assert out.shape == identity.shape
out = out + identity
如果断言失败,问题通常不是“残差思想不工作”,而是 stride、通道数或投影分支的配置不一致。将错误缩小到相加位置,比等待完整训练报错更有效。
结构理解与实验结论分开
残差连接提供了一条直接的信息路径,也改变了梯度传播方式。具体准确率仍然受到数据划分、优化器、训练轮数和随机性影响。
因此我会把结论分成两层:代码能够证明 F(x) + x 的结构;训练曲线只能描述对应设置下观察到的验证表现。二者不能互相替代。