ResNet101+FPN代码详解
1.ResNet
- resnet101结构:
resnet101代码:
1 | def resnet101(pretrained=False): |
1 | class ResNet(nn.Module): |
- 卷积层和BN层的初始化:
1 | for m in self.modules(): |
- 每个block结构:
block代码:
1 | class Bottleneck(nn.Module): |
resnet101设置:
1 | class resnet(_fasterRCNN): |
Faster RCNN利用了conv1到conv4-x的91层作为共享卷积层(即代码中的conv1,layer1,layer2,layer3)。从conv4-x开始分叉,一路经过RPN进行proposal选择,另一路送入ROIPooling层,把RPN结果输入ROI Pooling层,变成$7\times7$的特征。然后所有的输出经过con5-x计算,这里conv5-x起到全连接层fc的作用,然后经过分类器和边界框回归得到最终结果。整体框架如下:
对应代码在/faster-rcnn.pytorch/lib/model/faster_rcnn/faster_rcnn.py
中,如下:
1 | class _fasterRCNN(nn.Module): |
2.FPN
Bottom-up pathway
自下而上的通路是卷积网络backbone的前向计算,每个尺度的步长是2
.对于resnet
来说,我们使用最后的残差块的输出${C_2,C_3,C_4,C_5}$,对应于conv2,conv3,conv4,conv5
的输出。每层的步长分别为${4,8,16,32}$.
Top-down pathway and lateral connections
如何结合高低层的语义信息呢?就是:把更抽象、语义更强的高层特征图进行上采样,然后吧特征横向连接至前一层特征,因此得到加强的高层特征。自顶向下的过程采用了上采样进行,而横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合。如下图,这里$1\times1$的卷积核作用就是减少通道数,通过element-wise 相加。重复迭代过程,直至产生最精细的特征图。
金字塔中的所有层级共享分类、回归层。因此作者固定了所有特征图的维度,即通道数,表示为d.$d=256$.因此所有的额外的卷积层(比如P2)具有256维的输出。
在fasterRCNN中的应用
RPN
原本的RPN实现中,有一个$3\times3$的窗口在特征图上滑动,执行二分类和边界框回归。我们把$3\times3$的卷积层和后面接着的$1\times1$的用来分类和回归的卷积层叫做head,。是不是目标的标准和边界框回归的target是由anchor定义的。
FPN应用到RPN中时,我们调整如下:使用FPN代替了单一尺度的RPN。在每个特征金字塔层都加上刚刚说的$3\times3$和$1\times1$的head.因为head网络在每个位置都滑动,所以单独层没必要执行多尺度。
最后的定义:原本RPN中,anchor是在$13\times13$的特征图应用9中不同的尺度anchor,而本文,在多尺度的特征图上,应用每层固定scale的anchor尺寸。FPN中anchor在${P_2,P_3,P_4,P_5,P_6}$上分别对应尺度:${32^2,64^2,128^2,256^2,512^2},$ 每层使用的纵横比为{1:2,1:1,2:1}。最后特征金字塔共有15种anchor。
代码:
1 | class _RPN_FPN(nn.Module): |
Fast RCNN
1.特征图
在ROI Pooling时,输入为ROI和对应的特征图,因此需要对不同层级的金字塔定制不同尺度的ROI. 即需要对不同尺度的ROI确定应该使用哪一层的特征图作为ROI Pooling层的输入。因此定义了一个系数:
$$
k=[k_0+log_2(\sqrt{wh}/224)].\qquad(1)
$$
例如:ImageNet的标准输入是224,$k_0$基准设置为5,代表$P_5$层的输出。加入ROI尺寸为$w=112,h=112$,那么$k=5-1=4$.意味着该ROI应该使用$P_4$特征图作为输入。同时使用取整处理。
代码:
1 | #这个函数是确定某个ROI应该使用哪一层特征图进行ROIPooling的。 |
2.全连接
Fast RCNN论文中,head是指特定类别的分类器和回归器;
ResNet论文中,作者使用conv5作为Fast RCNN的head,对于不同level,这些head的参数共享。
FPN中,已经使用了conv5来构建特征金字塔,因此,作者加了两个隐含的1024维的全连接层,在分类层和回归层之前。
完整结构:
FPN代码:
1 | class _FPN(nn.Module): |
注意:代码很长,只截取了部分能够表示FPN结构的,大部分细节被删掉了,详细见源码.这个版本的代码还有点问题,训练出来的模型的精度竟然比faster rcnn的还低一丢丢!作者说:他正在调bug……
Reference
2.FPN代码细节