论文下载:SPNet-paper:Strip Pooling: Rethinking Spatial Pooling for Scene Parsing
代码下载:SPNet-github:Strip Pooling: Rethinking Spatial Pooling for Scene Parsing
前言
Strip Pooling Rethinking Spatial Pooling for Scene Parsing是2020CVPR会议上比较有代表性的语义分割类文章,思路新型,具有较高的创新价值,无论是提出的SPM还是MPM模块,都可以即插即用,可以套用在各类基础网络上,后面会用代码解释。
一、创新点
在之前语义分割实验已经证明,空间池化可有效捕获用于场景分析等像素级预测任务的远程上下文信息。本文在传统的N×N型Spatial pooling的基础上,提出了一种考虑狭长卷积核(1×N或N×1)的strip pooling策略。并基于Strip pooling,进一步研究了Spatial pooling体系结构设计。通过对文章的总结,可以罗列以下创新点和贡献:
- 从新设计了池化结构,提出了非对称卷积1X N和N X 1的空间Pooling结构;
- 使用strip pooling设计了两个即插即用的Strip Pooling Module和Mixed Pooling Module;
- 基于strp pooling和mixed pooling搭建了spnet。
二、主要工作
1.背景
提高卷积神经网络中远程依赖关系建模能力的方法有:
- 引入注意力机制:self-attention机制或non-local模块。缺点:它们会消耗大量内存。
- 卷积角度上考虑:空洞卷积或者深度可分离卷积等,可以不引入额外参数同时扩大卷积神经网络的感受野。缺点:对小目标不友好
- 池化角度上考虑:全局/金字塔池化等,通过结合不同池化核大小的池化层,为图像提供全局信息。
然而,空洞卷积和池化操作都是在正方形卷积中输入特征图并进行卷积运算。这限制了它们在捕获广泛存在于现实场景中的各向异性的上下文上的灵活性。
例如,在某些情况下,目标对象可能具有长条形结构(下图b中的草地)或离散分布(下图a中的柱子)。使用大的方形池窗口不能很好地解决这个问题,因为它将不可避免地合并来自无关区域的污染信息。
为了更有效地捕获长依赖关系,本文在空间池化层扩大卷积神经网络感受野和捕获上下文信息的基础上,提出了条形池化(strip pooling)的概念。作为全局池化的替代方案,条纹池化有两个优点:
- 它沿着一个空间维度部署一个长条状的池化核形状,因此能够捕获孤立区域的长距离关系,如图1a和1c的第一行所示部分所示。
- 在其他空间维度上保持较窄的内核形状,便于捕获局部上下文,防止不相关区域干扰标签预测。
在网络中使用这种长而窄的池内核,可以使语义分割网络能够同时聚合全局和局部上下文信息。这是与传统的从固定的正方形区域收集上下文的池化有本质的不同。
三、核心内容
基于条纹池化的想法,作者提出了两种即插即用的池化模块 — Strip Pooling Module (SPM) 和 Mixed Pooling module (MPM)。
2.1、SPM——Strip Pooling Module
SPM由侧重于沿着水平和垂直空间两个维度捕获远程上下文的路径组成。
图中的条纹池化,实际上和普通池化方法没有区别,也是求池化核(长条形区域)所对应的特征图上位置的像素值求平均。
主要流程:
- 输入一个特征图,这里实际上为C×H×W,为了方便讲解图中只画了一个通道。C个通道的特征图输入处理原理与这里所示的一个通道操作一模一样。
- 输入的特征图经过水平和竖直条纹池化后变为H×1和1×W,对池化核内的元素值求平均,并以该值作为池化输出值。
- 随后经过卷积核为3的1D卷积对两个输出feature map分别沿着左右和上下进行扩容,扩容后两个特征图尺寸相同,对扩容后的特征图对 应相同位置求和得到H×W的特征图。
- 之后通过1×1的卷积与sigmoid处理后与原输入图对应像素相乘得到了输出结果。
在上面的过程中,输出张量中的每个位置都与输入张量中的各种位置建立了关系。例如,在上图中,输出张量中以黑框为界的正方形与所有与它具有相同水平或垂直坐标的位置相连(被红色和紫色边框包围)。因此,通过多次重复上述聚合过程,可以在整个场景中构建长期依赖关系。此外,得益于element-wise乘法操作,该SPM也可以被视为一种视觉注意力机制。
SPM可以直接应用于任何预先训练的骨干网络,而无需从无到有地进行训练。与全局平均池化相比,条纹池化考虑的是较长但较窄的范围,而不是整个特征图,避免了在相距较远的位置之间建立不必要的连接。与需要大量计算来建立每对位置之间关系的基于注意力的模块(no-local )相比,SPM是轻量级的,可以很容易地嵌入到任何构建块中,从而提高捕获远程空间依赖关系和利用通道间依赖项的能力。
2.2代码的实现过程
由于原作者没有公开SPM代码,笔者根据文章描述写的代码,仅供参考,不对的地方欢迎大家一起讨论。
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torch
class SPM(nn.Module):
def __init__(self, input, in_channel, out_channel):
super(SPM, self).__init__()
inter_channel = in_channel / 4
b, c, h, w = input.shape
self.conv1 = nn.Sequential(F.conv2d(in_channel, inter_channel), nn.BatchNorm2d(inter_channel