在基础网络架构和代码库结构中,我展示了以下详细示意图(图 2),其中描述了标准 Base-RCNN-FPN 网络的设置, 以及他的配置文件[config file],这一次,我们将深入研究骨干网络——特征金字塔网络³(FPN)也就是所谓的the Feature Pyramid Network³ (FPN)。
Figure 2. Detailed architecture of Base-RCNN-FPN. Blue labels represent class names.
骨干网络的作用是从输入图像中提取特征图。这里还没有任何边界框、锚点或损失函数!
FPN的输入输出
首先,我们将澄清 FPN 的输入和输出。图 3 是 FPN 原理图的详细视图。
图 3. 带有 ResNet50 的 Base-RCNN-FPN 主干的详细架构。蓝色标签代表类名。模块内的 (a)、(b) 和 (c) 代表图 5 中详述的bottleneck类型。
input (torch.Tensor): (B, 3, H, W) image
B、H 和 W 分别代表批次大小、图像高度和宽度。注意输入颜色通道的顺序是蓝色、绿色和红色 (BGR)。如果将 RGB 图像作为输入,则检测精度可能会下降。
output (dict of torch.Tensor): (B, C, H / S, W / S) feature maps
B、H 和 W 分别代表批次大小、图像高度和宽度。注意输入颜色通道的顺序是蓝色、绿色和红色 (BGR)。如果将 RGB 图像作为输入,则检测精度可能会下
C 和 S 代表通道大小和步幅。默认情况下,所有比例的 C=256 和 P2、P3、P4、P5 和 P6 输出的 S = 4、8、16、32 和 64。
例如,如果我们将大小为 (H=800, W=1280) 的单个图像放入主干中,则输入张量大小为 torch.Size([1, 3, 800, 1280]) 并且输出字典应为:
output["p2"].shape -> torch.Size([1, 256, 200, 320]) # stride = 4
output["p3"].shape -> torch.Size([1, 256, 100, 160]) # stride = 8
output["p4"].shape -> torch.Size([1, 256, 50, 80]) # stride = 16
output["p5"].shape -> torch.Size([1, 256, 25, 40]) # stride = 32
output["p6"].shape -> torch.Size([1, 256, 13, 20]) # stride = 64
图 4 显示了实际输出特征图的样子。 “P6”特征的一个像素对应于比“P2”更宽的输入图像区域——换句话说,“P6”比“P2”具有更大的感受野。 FPN 可以提取具有不同感受野的多尺度特征图。
Figure 4: Example of input and output of FPN. The feature at the 0th channel is visualized from each output.
Code Structure⁴ for Backbone modeling
相关文件在detectron2/modeling/backbone目录下
├─modeling
│ ├─backbone
│ │ ├─backbone.py <- includes abstract base class Backbone
│ │ ├─build.py <- call builder function specified in config
│ │ ├─fpn.py <- includes FPN class and sub-classes
│ │ ├─resnet.py <- includes ResNet class and sub-classes
以下是类层次结构。
FPN (backbone/fpn.py)
├ ResNet (backbone/resnet.py)
│ ├ BasicStem (backbone/resnet.py)
│ └ BottleneckBlock (backbone/resnet.py)
└ LastLevelMaxPool (backbone/fpn.py
ResNet
ResNet⁵ 由一个主干块(
stem block)和包含多个瓶颈块(
bottleneck blocks)的“阶段”组成。对于 ResNet50,块结构是:
BasicStem
(res2 stage, 1/4 scale)
BottleneckBlock (b)(stride=1, with shortcut conv)
BottleneckBlock (a)(stride=1, w/0 shortcut conv) × 2
(res3 stage, 1/8 scale)
BottleneckBlock (c)(stride=2, with shortcut conv)
BottleneckBlock (a)(stride=1, w/o shortcut conv) × 3
(res4 stage, 1/16 scale)
BottleneckBlock (c)(stride=2, with shortcut conv)
BottleneckBlock (a)(stride=1, w/o shortcut conv) × 5
(res5 stage, 1/32 scale)
BottleneckBlock (c)(stride=2, with shortcut conv)
BottleneckBlock (a)(stride=1, w/o shortcut conv) × 2
ResNet101 and ResNet152 更多数量的 bottleneck blocks (a), 定义在: [code link]
(1) BasicStem (stem block) [code link]
ResNet 的“stem”块非常简单。它通过 stride=2 的 7×7 卷积和 stride=2 的最大池化对输入图像进行两次下采样。 stem 块的输出是一个特征图张量,其大小为 (B, 64, H / 4, W / 4)。
- conv1 (kernel size = 7, stride = 2)
- batchnorm layer
- ReLU
- maxpool layer (kernel size = 3, stride = 2)
(2) BottleneckBlock [code link]
Figure 5. Three types of bottleneck blocks.
bottleneck block 最初是在 ResNet paper⁵ 中提出的。该块具有三个卷积层,其卷积核大小分别为 1×1、3×3、1×1。 3×3 卷积层的输入和输出通道数小于块的输入和输出,以实现高效计算。
如图 5 所示,瓶颈块分为三种类型:
(a): stride=1, 没有shortcut conv
(b): stride=1, 有shortcut conv
(c): stride=2, 有shortcut conv
shortcut convolution (used in (b), (c))
ResNet将shortcut定义为输入和输出的特征的相加。对于res2到res5每一个阶段的第一个block,shortcut卷积层用于使得输入和输出的通道数一致。
downsampling convolution with stride=2 (used in (c))
对于res3,res4和res5这几个stages,使用了stride=2的卷积层对特征图进行下采样。同时,strid=2的shortcut卷积也被使用,主要目的是使得输入通道和输出通道的数量一致。
请注意,上面提到的“卷积层”包含卷积 torch.nn.Conv2d 和归一化(例如 FrozenBatchNorm⁶)。 [code link]在卷积和特征相加之后使用 ReLU 激活(见图 5)。
FPN
FPN 包含 ResNet 侧面的和输出卷积层、上采样器和最后一层 maxpool 层。[code link]
横向的卷积层(lateral convolution layers)[code link]
侧面卷积层将res2-res5每个阶段,输出的通道数不一致的特征图,通过卷积,得到 统一的256通道数的特征图。
输出卷积层(output convolution layers)[code link]
输出卷积层包含不改变通道数的 3×3 卷积。
前向处理(forward process)[code link]
Figure 6. Zooming into a part of FPN schematic that deals with res4 and res5.
H/32,FPN的前向处理(forward process)从res5输出开始(见图6)。
经过横向卷积(lateral convolution)后,256通道的特征图被馈送到输出卷积(output convolution),经过输出卷积后的结果,作为P5(1/32比例)注册到结果列表中。
256 通道的特征图也被馈送到上采样器(F.interpolate with最近邻插值法)并与 res4 输出(经过横向卷积后)相加。得到的特征图经过输出卷积,得到的结果张量 P4 也被注册到结果(1/16 比例)列表中。
上面的过程(从上采样到插入到结果列表)进行了 3 次,最终结果列表包含四个张量——即 P2(1/4 尺度)、P3(1/8)、P4(1/16 ) 和 P5 (1/32)。
LastLevelMaxPool [code link]
为了生成 P6 输出,将内核大小为 1 且步长为 2 的最大池化层添加到 ResNet 的最后一个块。该层只是将 P5 特征(1/32 比例)下采样到 1/64 比例特征,然后添加到结果列表中。
待续…
现在我们已经获得了多尺度特征图。在下一部分中,我们将了解数据加载器和真实数据准备。感谢您的阅读,请等待下一部分!
第 1 部分:简介 — 基本网络架构和代码库结构
第 2 部分(你在这里):特征金字塔网络
第 3 部分(下一个故事!):Data Loader 和 Ground Truth
第 4 部分:区域提案网络
第 5 部分:ROI(框)头
[1] This is a personal article and the opinions expressed here are my own and not those of my employer.
[2] Yuxin Wu, Alexander Kirillov, Francisco Massa, Wan-Yen Lo and Ross Girshick, Detectron2. https://github.com/facebookresearch/detectron2, 2019.
[3] T.-Y. Lin, P. Dollar, R. Girshick, K. He, B. Hariharan, and S. Belongie. Feature pyramid networks for object detection. In CVPR, 2017.
[4] as of Jan. 5, 2020. The file, directory, and class names are cited from the repository² ( Copyright 2019, Facebook, Inc. )
[5] Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. Deep residual learning for image recognition. In CVPR, 2016
[6] Why are the batchnorm parameters frozen? See this issue.
Digging into Detectron 2 — part 2 | by Hiroto Honda | Medium