简述
池化层(Pooling Layer)是CNN中常见的一种操作,池化层通常也叫做子采样(subsampling)或降采样(Downsampling),在构建CNN网络时,往往是用在卷积层之后,通过池化层来降低卷积层输出的特征维度,在有效减少网络参数的同时还可以防止过拟合现象。
说到池化操作,就会想到我们经常用的池化操作,即最大池化(Max Pooling)和平均池化(Average Pooling),实际上还有很多种池化操作(详细内容,参考下文)。假设输入大小为
i
i
i,输出大小为
o
o
o,kernel size为
k
k
k,stride为
s
s
s,则满足下面的公式:
o
=
i
−
k
s
+
1
o= \frac{i-k}{s} + 1
o=si−k+1;若有pad的时候,则满足下面公式:
o
=
i
+
2
×
p
−
k
s
+
1
o= \frac{i + 2 \times p -k}{s} + 1
o=si+2×p−k+1。
池化层的功能
主要功能如下:
1. 抑制噪声,降低信息冗余
2. 提升模型的尺度不变性,旋转不变性
3. 降低模型计算量
4. 防止过拟合
池化层的分类
最大/均值池化
最大池化是选择图像区域中最大值作为该区域池化后的值,方向传播的时候,梯度通过前向传播过程的最大值方向传播,其它位置梯度为0。
使用的时候,最大池化尤为重叠池化和非重叠池化,比如常见的
s
t
r
i
d
e
=
k
e
r
n
e
l
_
s
i
z
e
stride = kernel\_size
stride=kernel_size则属于重叠池化,重叠池化相比于非重叠池化不仅可以提升预测精度,同事在一定成都上可以缓解过拟合。
非重叠池化的一个应用例子是,yolov3-tiny的backbone最后一层,使用了一个stride=1,kernel size = 2的maxpooling进行特征提取的。
import torch
import torch.nn.functional as F
input = torch.Tensor(1, 3, 32, 32)
output = F.max_pool2d(input, kernel_size=2, stride=2)
print(output.shape)
output = F.max_pool2d(input, kernel_size=2, stride=2, padding=1)
print(output.shape)
'''
output:
torch.Size([1, 3, 16, 16])
torch.Size([1, 3, 17, 17])
'''
均值池化就是将选择的图像区中的所有值的平均值作为该区域池化后的值。
import torch
import torch.nn.functional as F
input = torch.Tensor(1, 3, 32, 32)
output = F.avg_pool2d(input, kernel_size=2, stride=2)
print(output.shape)
'''
output:
torch.Size([1, 3, 16, 16])
'''
中值池化
和中值滤波相似,但是被使用的机会比较少。中值池化具有学习边缘和纹理结构的特性、抗噪声能力比较强。
组合池化
组合池化是同时利用最大池化和均值池化的优势二引申的一种池化策略。常见组合策略有两种:Add和Concat。常常被用作分类任务的一个trick,其作用就是丰富特征层,Max Pooling更关注于局部特征,而Average Pooling更关注与全局特征。
import torch
import torch.nn.functional as F
def add_avg_max_pool2d(input):
max_output = F.max_pool2d(input, kernel_size=2, stride=2)
avg_output = F.avg_pool2d(input, kernel_size=2, stride=2)
return 0.5 * (max_output + avg_output)
def concat_avg_max_pool2d(input):
max_output = F.max_pool2d(input, kernel_size=2, stride=2)
avg_output = F.avg_pool2d(input, kernel_size=2, stride=2)
return torch.cat([max_output, avg_output], 1)
if __name__ == '__main__':
input = torch.Tensor(1, 3, 32, 32)
output = add_avg_max_pool2d(input)
print("add: " + str(output.shape))
output = concat_avg_max_pool2d(input)
print("concat: " + str(output.shape))
'''
output:
add: torch.Size([1, 3, 16, 16])
concat: torch.Size([1, 6, 16, 16])
'''
Spatial Pyramid Pooling
论文地址:Spatial Pyramid Pooling in Deep Convolutional-1406.4729
Spatial Pyramid Pooling简称SPP,SPP是在SPPNet中提出的,提出的时间是比较早,上文有关于SPP的论文链接;它被提出的初衷是为了解决CNN对输入图片尺寸的限制,即重复的卷积计算和固定输出。SPP的网络结构如下:
在yolov3中有一个网络结构叫yolov3-spp.cfg,这个网络比yolov.cfg达到更高的准确率,yolov3-spp.cfg的git网址,如下所示:
### SPP ###
[maxpool]
stride=1
size=5
[route]
layers=-2
[maxpool]
stride=1
size=9
[route]
layers=-4
[maxpool]
stride=1
size=13
[route]
layers=-1,-3,-5,-6
### End SPP ###
这里的SPP相当于原来的SPPNetworks的变体,通过使用多个kernel size的Max Pooling,最终将所有的feature map进行拼接,得到新的特征组合。
SPP的优点:
- 解决图片size不一致问题
- 从不同的角度进行特征提取,在聚合
- 体现了算法的robust特征 提高精度
Global Average/Max Pooling
global average pooling 与 average pooling 的差别就在 “global” 这一个字眼上。global 与 local 在字面上都是用来形容 pooling 窗口区域的。 local 是取 feature map 的一个子区域求平均值,然后滑动这个子区域; global 显然就是对整个 feature map 求平均值了。
同理,global max pooling亦是如此。
参考文献
https://www.jianshu.com/p/884c2828cd8e
Spatial Pyramid Pooling in Deep Convolutional-1406.4729
https://www.plob.org/article/22160.html