BasicBlock
和 Bottleneck
是在深度残差网络(ResNet)中使用的两种基本的残差块结构。
BasicBlock(基础块):
- 主要用于 ResNet-18 和 ResNet-34 这样的较浅网络。
- 包含两个卷积层(两个3x3卷积)。
- 输入和输出的通道数相同。
- 每个卷积层后面都有批归一化(Batch Normalization)和 ReLU 激活函数。
class BasicBlock(nn.Module): expansion = 1 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(BasicBlock, 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.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channels) self.downsample = downsample def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out
Bottleneck(瓶颈块):
- 主要用于 ResNet-50 及以上的深层网络。
- 包含三个卷积层(1x1、3x3、1x1),通过使用 1x1 卷积层减小维度,然后通过 3x3 卷积层增加维度。
- 输入和输出的通道数通常不同,但会通过 1x1 卷积层进行调整。
- 每个卷积层后面都有批归一化(Batch Normalization)和 ReLU 激活函数。
class Bottleneck(nn.Module):
expansion = 4
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(Bottleneck, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.conv3 = nn.Conv2d(out_channels, out_channels * 4, kernel_size=1, bias=False)
self.bn3 = nn.BatchNorm2d(out_channels * 4)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out)
out = self.conv3(out)
out = self.bn3(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
总的来说,Bottleneck 块引入了一个 1x1 卷积来减小和增加通道数,这有助于减轻模型的计算负担,并且在较深的网络中提供更好的性能。而 BasicBlock 块更简单,适用于较浅的网络。选择使用哪个块通常取决于网络的深度和任务的要求。