深度学习的池化操作

神经网络常用的池化操作,没有可学习参数,主要用于提取特征,降低特征数量

什么是池化(Pooling)?

  • 卷积神经网络中一个重要的概念,也叫做子采样(Subsampling)或降采样(Downsampling),在构建卷积神经网络时,往往会用在卷积层之后,通过池化来降低卷积层输出的特征维度,有效减少网络参数的同时还可以防止过拟合现象
  • 池化操作可以降低图像维度的原因,本质上是因为图像具有一种“静态性”的属性,这个意思是说在一个图像区域有用的特征极有可能在另一个区域同样有用
  • 对于视觉应用来说,池化的更正式名称为空间池化。时间序列应用通常将池化称为时序池化

池化有什么作用?

  • 增加感受野 : 在卷积层之间增加池化,可以扩大感受野(receptive field)
  • 保持不变性: 对微小区域内具有平移不变性,层数边多时,具有不变性的区域变大
  • 降低优化参数及难度: 相比较使用卷积层对数据进行下采样,池化层不需要优化参数,而且池化后数据量更少,也确保模型参数量更少

什么是最大池化(Max pooling)?

  • 类似于标准卷积(Convolution) 的过程,使用卷积核的方式扫描一个featrue map的一个区域,选择该区域的最大值作为输出

什么是平均池化(Average pooling)?

  • 类似于标准卷积(Convolution) 的过程,使用卷积核的方式扫描一个featrue map的一个区域,计算该区域的平均值作为输出

最大池化(Max pooling)与平均池化(Average pooling)的区别?

  • 一般来说,特征提取的误差主要来自两个方面:(1)邻域大小受限造成的估计值方差增大;(2)卷积层参数误差造成估计均值的偏移。平均池化(Average pooling) 能减小第一种误差,更多的保留图像的背景信息,最大池化(Max pooling) 能减小第二种误差,更多的保留纹理信息
  • 近些年比较主流的 ImageNet 上的分类算法模型都是使用的 max-pooling,很少使用 average-pooling,通常来讲,max-pooling 的效果更好,虽然 max-pooling 和 average-pooling 都对数据做了下采样,但是 max-pooling 感觉更像是做了特征选择,选出了分类辨识度更好的特征,提供了非线性

什么是反池化(UnPooling)?

  • 一种上采样技术,将低分辨率特征还原为高分辨率特征
  • 以最大池化(Max pooling)为例,池化时记住保留最大信息的位置,反池化直接将最大信息填回去,参考:最大池化层反向传播
  • 以平均池化(Average pooling)为例,池化时记住保留最大信息的位置,反池化直接将最大信息填回去,参考:平均池化层反向传播

平均池化层如何做反向传播?

  • 平均池化层用于减小图片分辨率,操作过程中没有“可学习参数”,但是由于其输入和输出的对应关系变化,所以需要重新计算某平均池化层输出关于输入的梯度,以便把梯度往更后的地方传递
  • 正向传播:把一个patch中的值求取平均来做pooling
  • 反向传播:把某个元素的梯度等分为n份分配给前一层,这样就保证池化前后的梯度(残差)之和保持不变

最大池化层如何做反向传播?

  • 最大池化层用于减小图片分辨率,操作过程中没有“可学习参数”,但是由于其输入和输出的对应关系变化,所以需要重新计算某最大池化层输出关于输入的梯度,以便把梯度往更后的地方传递
  • 正向传播:把patch中最大的值传递给后一层,而其他像素的值直接被舍弃掉
  • 反向传播:根据梯度之和不变的原则, max pooling 操作需要记录下池化操作时到底哪个像素的值是最大,反向传播时直接把梯度传给这个位置即可

池化层的参数量及计算量?

  • **参数量:**池化层没有参数量
  • **计算量:**平均池化的每个输出需要进行Kernelw×Kernelh1Kernel_w \times Kernel_h -1次的加法运算和1次减法运算,所有输出即是计算

什么是全局池化(Global Pooling)?

  • 一般池化(Pooling) 指的是局部池化,即指定池化窗口大小及步长,通过类似标准卷积(Convolution)扫描特征,进行池化操作
  • 全局池化在NIN 中提出,针对整个特征图进行一次池化操作,可以是平均池化(Average pooling),也可以是最大池化(Max pooling)
  • 优点: 全局池化一般用于网络的深层,用来收集高级特征,比如替代全连接层作特征展开,不仅减少参数,还可以减少过拟合
  • 缺点: 缺少全连接的学习,需要网络浅层学习到更加高级的信息,因此收敛慢;也因为网络学习到的特征都在浅层,所以泛化能力弱,不利于迁移学习

什么是全局平均池化(Global Average Pooling)?

  • 平均池化(Average pooling) 是针对一个区域进行池化,而全局平均池化针对整个featrue map,一般是用来替换全连接层

什么是全局最大池化(Global Max Pooling)?

  • 最大池化(Max pooling)是针对一个区域进行池化,而全局最大池化针对整个featrue map,一般是用来替换全连接层

什么是重叠池化(Overlapping Pooling)?

  • 与一般池化操作相同,但是池化范围PsizeP_{size}与滑窗步长stride关系为Psize>strideP_{size}>stride,同一区域内的像素特征可以参与多次滑窗提取,得到的特征表达能力更强,但计算量更大
  • AlexNet中提出和使用,不仅可以提升预测精度,同时一定程度上可以减缓过拟合

什么是随机池化(Stochastic-Pooling)?

  • 只需对feature map中的元素按照其概率值大小随机选择,即元素值大的被选中的概率也大。而不像最大池化(Max pooling)那样,永远只取那个最大值元素
  • 随机池化首先根据特征图值的大小概率性选择位置,然后取该位置的最大池化(Max pooling) 或 平均池化(Average pooling) 值作为输出,下图使用多项分布抽样(FF)、均匀分布抽样(UN)进行随机位置选择,最大池化和最小池化的效果,可以看出最大池化可以比较好的保留图片中的纹理信息,而平均池化已经失去可辨识的纹理信息

什么是中值池化?

  • 和cv: :medianBlur很像,但是用的非常少,中值池化也具有学习边缘和纹理结构的特性,抗噪声能力比较强

什么是组合池化?

  • 同时利用最大值池化与均值池化两种的优势,常见组合策略有两种:Cat与Add
  • 常常被当做分类任务的一个trick,其作用就是丰富特征层,maxpool更关注重要的局部特征,而average pooling更关注全局特征

什么是双线性池化(Bilinear Pooling)?

  • 对两种特征提取器进行融合,再用于fine-grained分类

什么是幂平均池化(Power Average Pooling) ?

  • 基于平均池化和最大池化的结合,它利用一个学习参数来确定这两种方法的相对重要性;当时,使用局部求和,当时,使用最大池化

什么是DPP池化(Detail-Preserving Pooling, DPP)?

  • 一种自适应的池化方法-DPP池化 ,该池化可以放大空间变化并保留重要的图像结构细节,且其内部的参数可通过反向传播加以学习

什么是局部重要性池化(Local Importance Pooling, LIP)?

  • 从局部重要性的角度提出了局部重要性池化,通过基于输入学习自适应重要性权重,LIP可以在下采样过程中自动增加特征判别功能

什么是软池化(Soft Pooling)?

  • 软池化 Soft Pooling是基于softmax加权的方法来保留输入的基本属性,同时放大更大强度的特征激活。与maxpooling不同,softpool是可微的,所以网络在反向传播过程中为每个输入获得一个梯度

什么是S3池化(S3Pool)?

  • 一种随机池化(Stochastic Pooling)策略,集成了随机池化Stochastic Pooling与最大值池化Max Pooling

什么是图池化?

  • 基于条件随机场的,它是将图池化视为一个节点聚类问题,并使用 CRF 在不同节点的分配之间建立关系。并通过结合图拓扑信息来推广这个方法,使得图池化可以控制 CRF 中的成对团集

什么是空间金字塔池化 (Spatial Pyramid Pooling, SPP)?

  • 典型的卷积神经网络基础结构: 卷积层->池化层->全连接层,由于全连接层的输入维数必须提前固定,因此第一层卷积的输入尺寸是固定的,一般通过裁剪、warp 拉伸等操作把图片变换成固定尺寸,再输入网络,但是些操作在一定程度上会导致图片信息的丢失或者变形
  • 空间金字塔池化: 把卷积操作之后的特征图,以不同大小的块(池化框)来提取特征,分别是 4 x 4,2 x 2,1 x 1,将这三张网格放到下面这张特征图上,就可以得到 16+4+1=21 种不同的块,从这 21 个块中,每个块提取出一个特征(提取方式有平均池化、最大池化等),这样就得到了固定的 21 维特征向量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class SPP(nn.Module):
    # Spatial Pyramid Pooling (SPP) layer https://arxiv.org/abs/1406.4729
    def __init__(self, c1, c2, k=(5, 9, 13)):
    super().__init__()
    c_ = c1 // 2 # hidden channels
    self.cv1 = Conv(c1, c_, 1, 1)
    self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
    self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
    def forward(self, x):
    x = self.cv1(x)
    with warnings.catch_warnings():
    warnings.simplefilter('ignore')
    return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))

什么是快速金字塔池化 (Spatial Pyramid Pooling - Fast, SPPF)结构?

  • YOLOv 5 改空间空间金字塔池化(SpatialPyramidPooling,SPP) 得到,主要思想是:将输入串行通过多个不同大小的 MaxPool,然后做进一步融合,两者的作用是一样的,但后者效率更高
  • SPPF 结构是将输入串行通过多个 5 x 5 大小的 MaxPool 层,这里需要注意的是串行两个 5 x 5 大小的 MaxPool 层是和一个 9 x 9 大小的 MaxPool 层计算结果是一样的,串行三个 5 x 5 大小的 MaxPool 层是和一个 13 x 13 大小的 MaxPool 层计算结果是一样的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SPPF(nn.Module):
# Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
def __init__(self, c1, c2, k=5): # equivalent to SPP(k=(5, 9, 13))
super().__init__()
c_ = c1 // 2 # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_ * 4, c2, 1, 1)
self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
def forward(self, x):
x = self.cv1(x)
with warnings.catch_warnings():
warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
y1 = self.m(x)
y2 = self.m(y1)
return self.cv2(torch.cat((x, y1, y2, self.m(y2)), 1))

什么是 SimSPPF?

  • YOLOv 6 提出的模块,感觉 SPPF 只差了一个激活函数,简单测试了一下,单个 ConvBNReLU 速度要比 ConvBNSiLU 快18%

什么是空洞卷积金字塔池化 (Atrous Spatial Pyramid Pooling, ASPP)?

  • DeepLabv2-20230408142623
  • 在空间金字塔池化(SpatialPyramidPooling,SPP) 的基础上,结合空洞卷积(Atrousconvolution) 可在不丢失分辨率(即不进行下采样)的情况下扩大卷积核的感受野,有助于考虑不同的物体比例
  • 根据卷积的输出计算torch.nn.Conv2d,对于卷积核为 3 x 3 的空洞卷积,只要其 dilation=padding,stride=1,卷积层输出的大小保持不变
    1
    2
    3
    4
    5
    6
    7
    >>> input = torch.randn(5, 8, 56, 128)
    >>> m = torch.nn.Conv2d(8, 33, (3, 3), padding=(4, 4), dilation=(4, 4));
    >>> m(input).shape
    torch.Size(\[5, 33, 56, 128])
    >>> m = torch.nn.Conv2d(8, 33, (3, 3), padding=(24, 24), dilation=(24, 24));
    >>> m(input).shape
    torch.Size(\[5, 33, 56, 128])

什么是 SPPCSPC?

  • YOLOv 7 中使用的 SPP 结构,在 COCO 数据集上表现优于 SPPF
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class SPPCSPC(nn.Module):
    # CSP https://github.com/WongKinYiu/CrossStagePartialNetworks
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=(5, 9, 13)):
    super(SPPCSPC, self).__init__()
    c_ = int(2 * c2 * e) # hidden channels
    self.cv1 = Conv(c1, c_, 1, 1)
    self.cv2 = Conv(c1, c_, 1, 1)
    self.cv3 = Conv(c_, c_, 3, 1)
    self.cv4 = Conv(c_, c_, 1, 1)
    self.m = nn.ModuleListnn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
    self.cv5 = Conv(4 * c_, c_, 1, 1)
    self.cv6 = Conv(c_, c_, 3, 1)
    self.cv7 = Conv(2 * c_, c2, 1, 1)
    def forward(self, x):
    x1 = self.cv4(self.cv3(self.cv1(x)))
    y1 = self.cv6(self.cv5(torch.catx1] +m(x1) for m in self.m], 1)))
    y2 = self.cv2(x)
    return self.cv7(torch.cat((y1, y2), dim=1))