如第 14.9 节所述,语义分割在像素级别对图像进行分类。全卷积网络 (FCN) 使用卷积神经网络将图像像素转换为像素类( Long et al. , 2015 )。与我们之前在图像分类或目标检测中遇到的 CNN 不同,全卷积网络将中间特征图的高度和宽度转换回输入图像的高度和宽度:这是通过 14.10 节介绍的转置卷积层实现 的. 因此,分类输出和输入图像在像素级别具有一一对应关系:任何输出像素的通道维度都包含相同空间位置的输入像素的分类结果。
14.11.1。该模型
在这里,我们描述了全卷积网络模型的基本设计。如图 14.11.1所示,该模型首先使用 CNN 提取图像特征,然后通过1×1卷积层,最后通过 14.10 节介绍的转置卷积将特征图的高度和宽度转换为输入图像的高度和宽度。因此,模型输出与输入图像具有相同的高度和宽度,其中输出通道包含相同空间位置的输入像素的预测类别。
下面,我们使用在 ImageNet 数据集上预训练的 ResNet-18 模型来提取图像特征并将模型实例表示为 pretrained_net
。该模型的最后几层包括全局平均池化层和全连接层:全卷积网络不需要它们。
[Sequential(
(0): BasicBlock(
(conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
),
AdaptiveAvgPool2d(output_size=(1, 1)),
Linear(in_features=512, out_features=1000, bias=True)]
(HybridSequential(
(0): Activation(relu)
(1): GlobalAvgPool2D(size=(1, 1), stride=(1, 1), padding=(0, 0), ceil_mode=True, global_pool=True, pool_type=avg, layout=NCHW)
(2): Flatten
),
Dense(512 -> 1000, linear))
接下来,我们创建全卷积网络实例net
。它复制了 ResNet-18 中的所有预训练层,除了最终的全局平均池化层和最接近输出的全连接层。
给定高度和宽度分别为 320 和 480 的输入,正向传播将net
输入高度和宽度减小到原始的 1/32,即 10 和 15。
接下来,我们使用一个1×1卷积层将输出通道的数量转换为 Pascal VOC2012 数据集的类数 (21)。最后,我们需要将特征图的高度和宽度增加 32 倍,以将它们变回输入图像的高度和宽度。回想一下7.3 节中如何计算卷积层的输出形状。自从 (320−64+16×2+32)/32=10和 (480−64+16×2+32)/32=15,我们构造一个转置卷积层,步幅为32,将内核的高度和宽度设置为64,填充到16. 一般来说,我们可以看到对于 strides, 填充s/2 (假设s/2是一个整数),内核的高和宽2s,转置卷积将使输入的高度和宽度增加s次。
num_classes = 21
net.add_module('final_conv', nn.Conv2d(512, num_classes, kernel_size=1))
net.add_module('transpose_conv', nn.ConvTranspose2d(num_classes, num_classes,
kernel_size<