Mask RCNN阅读笔记
目录
一. 文章主题介绍:
该文章主要是通过扩展Faster RCNN,实现实例分割的功能;具体来说,就是在后面添加了一个mask分支用于像素级别的预测(也就是实例分割)。如下图所示:
这个分支仅仅增加很好的计算的消耗
论文作者:Kaiming He(first),CVPR 2017的会议best paper。
二. 文章核心设计:
2.1 mask分支损失函数的计算
新的思想:
1. 不同于FCNs系列的工作——每个像素即预测类别也预测是否被为对象;而Mask RCNN 分离 了每个像素是对象以及属于哪个类别的预测——类别预测直接从类别预测Cls分支中读取。
2. 这种分离的预测存在另一种特性:就是像素级的预测掩码(mask)没有类别竞争。
mask分支的执行: mask分支的输出为针对每个RoI 有一个
Km2
K
m
2
-dimensional输出。掩码为二值掩码——只有0或1。只用来预测该像素级别的点是否为对象。
Mask 分支代码设计示例:
class Model ...
# 前层输出(N,1024,7,7)
self.out_mask =
nn.Sequential(
nn.ConvTranspose2d(self.out_channels,
256, kernel_size=2, stride=2), #(N,256,14,14)
nn.ReLU(inplace=True),
nn.Conv2d(256, nb_classes - 1, kernel_size=1, stride=1),
# (N,20,14,14) VOC 数据集,20个类别
nn.Sigmoid(), # sigmoid激活
)
mask分支的损失计算: 利用平均二值交叉验证损失函数 (binary cross-entroy loss) ,并且根据每个RoI所关联的类别k,只计算该类别k对应的mask损失计算,其他非k的mask不参与损失计算,也就是每个ROI只计算(1,1,m,m)大小的损失。
损失代码:
class class_loss_mask(nn.Module):
def __init__(self, obj_classes=20):
super(class_loss_mask, self).__init__()
self.obj_classes = obj_classes
def forward(self, preds, targets):
'''
:param preds: (num_rois,num_class,pool,pool)=(20,14,14)
:param targets: (num_rois,num_class,pool,pool)
:return:
'''
weight = targets[:, :self.obj_classes, :, :]
y_true = targets[:, self.obj_classes:, :, :]
weight = Variable(torch.from_numpy(weight).float()).cuda()
y_true = Variable(torch.from_numpy(y_true).float()).cuda()
preds = preds * weight #用于屏蔽非k的类别的损失计算,只计算有效类别的损失
N = torch.sum(weight)
return F.binary_cross_entropy(preds, y_true, size_average=False) / N
2.2 ROIAlign的一些改进
1.该技术要解决的问题描述:
[12,18]说明了ROIPooling是粗糙的对齐,ROIPooling存在两个量化阶段:
RoI边界量化阶段:原图box与RoI之间的量化, RoIPooling主要采用round[x/16]的方式,16是特征图的步长。
ROI到Pool盒(bin)阶段:RoI与提取的特征之间的量化,特征图(h,w) –> (pool,pool)pool=7或14。作为后面Fast RCNN阶段的输入。
这两种量化阶段导致了RoI与提取的特征之间的错位(misalignment)问题。
2.具体的实现:
1)为了修复这种不对齐的方式,针对两个量化阶段进行修改,在RoI边界和pool盒(box)阶段避免任何量化:
用 x/16代替[x/16],即对步长不做round操作。
对每个RoI在四个位置上执行bilinear interpolation(双线差值法)操作,然后再用max或者average pool操作。
2)关键代码如下所示:
class RoIAlign: ....
region = x_img[:, :, y:(y + h + 1), x:(x + w + 1)]
region = F.upsample_bilinear(region, (h, w)) # 对RoI使用bilinear操作
region = self.adaptive_max_pool(region)
3) x/16与[x/16]的区别:
4)bilinear interpolation的具体操作示意图:
https://github.com/soeaver/Pytorch_Mask_RCNN/blob/master/README/RoIAlign.png
扩展阅读(Spatial transformer networks)
带来的好处:提高了掩码相对精度10%到50%
5 ) 编写代码过程中,mask 解析过程出现BUG的说明
2.3 两种基础网络
为了验证Mask RCNN的一般性,它的backbone使用了ResNet和FPN两种类型的基础网络架构用于提取特征,两个结构对应的mask 分支的示意图:
FPN获得的性能优于ResNet的性能;主要是FPN使用金字塔特征结构,将low-level的特征与high-level的特征融合,能提取更加准确的位置等特征信息。
扩展阅读FPN(Feature Pyramid Networks for Object Detection)
三. 打磨实验:
3.1 实验参数的配置:
参数 | 值 |
---|---|
min_side | 800 pixels |
pos:neg | 1:3 |
learning_rate | 0.02(160k),0.002(120k) |
weight_decay | 0.0001 |
momentum | 0.9 |
gradient method | SGD |
RoI数目(ResNet/FPN) | (64/512) |
anchors | 5 scales ,3 aspect ratios |
mini_batch | 16 (on 8 GPUs) |
training set | COCO (80 classes) |
—test—- | |
proposal number | 300(ResNet), 1000(FPN) |
mask branch | 取得分top 100的RoI对应的mask输出 |
mask threshold | 0.5 就是预测大于0.5的标位1 |
3.2 主要的一些对比实验
(实验图片来自于原始论文)
1. 基础网络结构ResNet和FPN的对比
1)网络深的比浅的性能高 (然而,根据论文,对于对象检测系统来说不一定越深的、越先进的网络性能就越好)
2)FPN backbone优于ResNet的backbone .
2. FCNs系列的联合预测方式与Mask RCNN这种分离的预测方式对比
1)实验结果表明,这种分离的预测方式比FCNs系列性能好的多,其他分支确定类别和box,而mask只需要预测二值掩码即可(sigmoid+binary loss)
3. 类别指定和类别不可知的mask方式的对比(也就是求mask时是否利用cls分支的结果选择对应的mask进行解析)
1)如下图所示的对比实验,结果为Class-Specific .vs Class-Agnotic——30.3 AP vs 29.7 AP,表明了分离的mask分支独立有效性 (不知理解是否正确,有待考察)
4. RoIAlign与RoIPool,RoIWarp等方式的对比
1) 各个数据表明,RoIAlign优于ROIPool
2) RoIAlign 对max或者average pool不敏感
3) 对于更大的32跨度的结构,RoIAlign优势更加突出,表明RoIAlign一定程度改善大跨度的问题
4) 对于FPN backbone的网络结构,RoIAlign在对象识别的方面表现优势不明显,而在关键点检测方面,表现很明显 (第二、三个表)
5. Mask分支使用MLP还是使用FCN结构(全卷积层)的对比
1) 使用FCN结构作为mask分支表现优于MLP,因为卷积层保持了空间布局的信息。
6. Mask RCNN与其他前沿工作的对比
1) 与FCIS和MNC工作的对比,Mask RCNN的性能明显要好
2) 如下面效果图展示,FCIS存在systematic artifacts——也就是掩码中存在一些杂质,瑕疵。而Mask RCNN没有这种问题 (如红圈标注)
7. mask 分支对检测框预测的影响
1) Mask 分支对Box的预测有一定的提升,可能是多任务训练的原因。
2) 通过列表观察可以发现,Mask 的AP和Box AP很相近,表明Mask RCNN拉近了box预测和更加有挑战性的实例分割预测的距离。
四. 收获/总结/启发:
1) 提出了一种新的思想,将像素级的预测——分离类别预测和掩码预测**
2) 为了解决RoIPool错位问题,提出了RoIAlign 层——使用x/16而不是[x/16]和使用bilinear采样避免ROI量化**
补充说明
需要扩展学习的:
1)扩展阅读FPN(Feature Pyramid Networks for Object Detection)
2)扩展阅读(Spatial transformer networks)
3)对多种模型FasterRCNN,SSD等进行综合考察的论文
4)FCNs系列的文章
5)论文中Related Work中的文章需要研读一下
6) DeepMask系列文章1,2,3
注:(一些网页需要外网VPN链接)
引用
1 https://github.com/soeaver/Pytorch_Mask_RCNN/blob/master/README/RoIAlign.png
2 http://papers.nips.cc/paper/5854-spatial-transformer-networks.pdf
3 https://arxiv.org/pdf/1703.06870
4 https://arxiv.org/pdf/1612.03144
5 http://arxiv.org/abs/1611.10012