传统的CNN网络要求固定尺寸的图像输入(比如224x224),使得数据集的图片为了适应特定尺寸,不得不剪切或扭曲。然而,剪切的图片不一定包含整个物体,扭曲的图片会导致位置错乱。最终导致识别准确率因内容缺失或错乱而只能妥协。
为什么传统CNN需要固定尺寸的图像输入?一个CNN通常由两部分组成:卷积层和全连接层。
所以,本文提出了SPP层,它接在卷积层之后,全连接层之前。如下图所示:
卷积层和池化层都能接受不同尺寸的输入。其输出和输入的比例基本近似…
卷积层能接受任意尺寸的输入,但输出的尺寸也是任意的。而全连接层要求固定长度的输入。为了满足这个条件,我们将卷积层末尾处的pooling层替换成spp层。如下图所示。首先,spp层的输入是一个特征图。在16x、4x和1x三种尺度上分别作pooling,每个空间块会使用对应的filter(本文都使用max pooling)作pooling。输出则是kM长度的向量,其中M是空间块数,k是最后一层卷积层的filter数。之后,固定长度的向量会输入到全连接层。
举个例子:
spp层是如何做到输入任何尺寸的特征图,都能输出同样长度的向量?其实spp层是用多种参数的max pooling层组合完成效果的。
如下图所示,假设以224*224的尺寸输入网络时,spp层由如下的3个pooling层(pool3x3,pool2x2和pool1x1)组成,其输出接入fc6。卷积层
c
o
n
v
5
conv_5
conv5输出的特征图为13x13,所以3个pooling层的输出尺寸为3x3,3x3和1x1。
假如在下个epoch,以180×180的图片输入网络呢?
c
o
n
v
5
conv_5
conv5的特征图输出尺寸为10x10,那么对于axa=10x10尺寸的图片,只要设置pooling参数为
w
i
n
=
⌈
a
/
n
⌉
win=\left \lceil a/n \right \rceil
win=⌈a/n⌉和
s
t
r
=
⌊
a
/
n
⌋
str=\left \lfloor a/n \right \rfloor
str=⌊a/n⌋,即可让输出与180-network的输出维度等同于240-network的输出了。而两个网络其它的参数是完全相同的。
换句话说,我们只用两个共享参数的网络(两者间只有spp层的win和str参数不同),就能适应两种尺寸输入的图片了。为了节约开销,我们通常在一个epoch中使用一个尺寸的输入(比如224 x 224),并在另一个epoch中使用另一个尺寸的输入(180 x 180)。在两个epoch间,网络仅会切换spp层的滑动参数,而其它层维持不变。
如何得到不同输入尺寸的图片? 步骤如下:
在本文训练中,不同epoch应当输入一样的内容。并不是说第一个epoch里输入第一组224x224的图片,到下个epoch就输入180x180的其它图片了。图片的素材在不同epoch间是相同的。
如何理解SPP层的实现?
SPP的multi-size training部分,它直接将224x224的图片缩放成了180x180?所以说,使用的图片都是一样的,只是大小不同?
个人认为是的。数据集还是同一份,刚开始图片的大小不一。在224-network中,将原图剪裁出224x224,训练一个epoch。在180-network中,将224x224缩放为180x180,训练一个epoch。
为什么第一次输入是224x224,输出是13x13,第二次输入是180x180,输出却成了10x10?缩放比例并不相等
根据卷积层输出大小计算,卷积层的输出为
O=(I-K+2P)/S+1
。
所以说,SPP-net的做法只是在epoch间切换下pooling层的参数就完事了?
SPP-net的缺点见 SPP(Spatial Pyramid Pooling)网络 结尾。