讲一下resblock的跳跃连接,以及连接前后的shape保持(通过padding保持shape不变)
ResNet 残差块(ResBlock)的跳跃连接 & 形状保持
ResNet(Residual Network)通过 残差块(Residual Block, ResBlock) 解决了深度网络的梯度消失问题。其核心是跳跃连接(Skip Connection),可以让梯度直接从后面的层传播回前面的层,使深度网络更容易优化。
1. ResBlock 的跳跃连接
(1) 结构
ResBlock 的核心是恒等映射(Identity Mapping):
• 输入 x 直接加到输出 F(x) 上:
y = F(x) + x
其中:
• F(x) 由 两层 3×3 卷积 + BN + ReLU 组成。
• 跳跃连接(Skip Connection) 直接把 x 传递到输出端。
• ReLU(y) 作为最终输出。
(2) 形状保持
卷积计算公式
对于 标准卷积(不考虑分组卷积或空洞卷积),输出特征图的尺寸(H_out 和 W_out)可以用以下公式计算:
• :输入特征图的高度和宽度
•:输出特征图的高度和宽度
• kernel_size:卷积核的大小(例如 3×3,此时 kernel_size=3)
• stride:步幅,决定滑动窗口移动的步长
• padding:填充的像素数,使得输入和输出尺寸一致
一般情况:
• 两次 3×3 卷积 具有 stride=1, padding=1,因此 输入 x 和 F(x) 的形状一致:
• 因此,直接相加不会改变形状。
如果通道数不匹配或 stride=2(降采样情况):
• 需要使用 1×1 卷积 进行 投影变换(Projection),保证 x 和 F(x) 形状一致:
2. 代码实现
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义 ResNet 的 BasicBlock(适用于 ResNet-18/34)
class BasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super(BasicBlock, self).__init__()
# 3x3 卷积核,保持 shape
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)
# 处理输入 x 和 F(x) 形状不匹配情况
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):
identity = self.shortcut(x) # 跳跃连接(可能做 1x1 卷积调整通道)
out = F.relu(self.bn1(self.conv1(x))) # 第一个 3x3 卷积
out = self.bn2(self.conv2(out)) # 第二个 3x3 卷积
out += identity # 跳跃连接
out = F.relu(out) # 最终输出
return out
# 例子:输入 (1, 64, 32, 32) 通过 BasicBlock
x = torch.randn(1, 64, 32, 32)
block = BasicBlock(64, 64, stride=1)
output = block(x)
print(output.shape) # torch.Size([1, 64, 32, 32]) 形状保持
3. 形状变化分析
情况 | 卷积核 | stride | padding | 通道变化 | H, W 变化 | 是否需要 1×1 变换 |
---|---|---|---|---|---|---|
普通情况 | 3×3 | 1 | 1 | 相同 | 不变 | 不用 1×1 卷积 |
下采样 | 3×3 | 2 | 1 | 变大 | H, W 降一半 | 需要 1×1 卷积 |
通道增加 | 3×3 | 1 | 1 | 变大 | 不变 | 需要 1×1 卷积 |
4. 总结
✅ 跳跃连接是 ResNet 的核心,使深度网络更易训练。
✅ 如果 stride=1,两次 3×3 卷积 + padding=1,形状不变,直接相加。
✅ 如果 stride=2 或通道数变化,则用 1×1 卷积调整 x 形状,确保可以相加。
✅ 这样既能保持特征信息,又能优化梯度流动,提高训练稳定性! 🚀