这部分的计算其实就是感受野大小的计算。
卷积神经网络CNN中,某一层输出结果中一个元素所对应的输入层的区域大小,被称作感受野receptive field。感受野的大小是由kernel size,stride,padding , outputsize 一起决定的。下面这个图来感受一下!
卷积过程中的词语含义:
28 × 28 28\times28 28×28的输入图片,输入图片尺寸 W = 28 W=28 W=28
5 × 5 5\times5 5×5的local receptive fields(局部感受野,也叫滑窗,卷积核)—卷积核大小 K = 5 K=5 K=5
滑动步长(stride)
当 W = 28 W=28 W=28, K = 5 K=5 K=5, s t r i d e = 1 stride=1 stride=1时,可以得到 24 × 24 24\times24 24×24的隐层神经元。
我们可以推出公式:
隐藏层边长 = ( W − K ) / S + 1 隐藏层边长=(W-K)/ S +1 隐藏层边长=(W−K)/S+1
注意:不过有时候为了控制输出的隐藏层空间分布会在输入层外围做零填充,假设填充 P P P个像素,此时:
边长 = ( W − K + 2 P ) / S + 1 边长=(W-K+2P)/ S + 1 边长=(W−K+2P)/S+1
特别的当 S = 1 S=1 S=1时,设置零填充为 P = ( K − 1 ) / 2 P = (K-1) / 2 P=(K−1)/2,可以保证输入层与输出层有相同的空间分布 。
综上所述:
隐藏层边长(输出的边长) = ( W − K + 2 P ) / S + 1 隐藏层边长(输出的边长)= (W - K + 2P)/ S + 1 隐藏层边长(输出的边长)=(W−K+2P)/S+1
其中 W W W是输入特征的大小, K K K是卷积核大小, P P P是填充大小, S S S是步长(stride)。
用英文表达:
output field size
= ( input field size
- kernel size
+ 2 × 2\times 2×padding
) / stride
+ 1
output field size
是卷积层的输出,input field size
是卷积层的输入。
那么我们该如何计算卷积层的输入呢?即我们如何计算前一层的感受野的大小?
input field size = (output field size - 1)* stride - 2*padding + kernelsize
卷积神经网络CNN中,某一层输出结果中一个元素所对应的输入层的区域大小,被称作感受野receptive field。感受野的大小是由kernel size,stride,padding , outputsize一起决定的。
通常,我们需要知道网络里面任意两个feature map之间的坐标映射关系(一般是中心点之间的映射),如下图,我们想得到map 3上的点p3映射回map 2所在的位置p2(红色框的中心点)。
在第 i i i层的坐标: p i p_i pi
第 i i i层的步长: s i s_i si
第 i i i层的卷积核的大小: k i k_i ki
第 i i i层填充的大小:padding
计算公式:
对于Conv或pooling层: p i = s i × p i + 1 + [ ( k i − 1 ) / 2 − p a d d i n g ] p_i=s_i\times p_{i+1}+[(k_i - 1) / 2-padding] pi=si×pi+1+[(ki−1)/2−padding]
对于Neuronlayer(ReLU/Sigmoid/…): p I = p i + 1 p_I=p_{i+1} pI=pi+1
上面是计算任意一个layer输入输出的坐标映射关系,如果是计算任意feature map之间的关系,只需要用简单的组合就可以得到,下面是一个简单的例子:
到这里大致明白了一些皮毛。
为了更好的去理解论文中这样定义的来源,我去看了看何凯明大神ICCV2015上演讲的PPT:
《 iccv2015_tutorial_convolutional_feature_maps_kaiminghe.》
问题:如何计算感受野区域的中心?
一个简单的解决方案是:对每一层,填充零元素 P = F / 2 P = F / 2 P=F/2向下取整,这样的话,在每一个特征图上坐标为(0,0)的响应点的感受野是以输入图像坐标为(0,0)的点为中心的,坐标为 ( x , y ) (x,y) (x,y)的点的感受野是以 ( S × x , S × y ) (S\times x,S\times y) (S×x,S×y)为中心的, S S S为步长。
最后给出了计算的通解。
算是有了点眉目,可是还是不知道怎么回事,只知道有那么个公式,却不知道怎么推出来的,满心的疑惑。
SPP-Net对上面的坐标对应关系作了一定的简化,简化过程如下:
令每一层的padding都为:
p a d d i n g = ⌊ k i 2 ⌋ → p i = s i × p i + 1 + ( k i − 1 2 − ⌊ k i 2 ⌋ ) padding = \lfloor \frac{k_i}{2} \rfloor \rightarrow p_i = s_i \times p_{i+1} + (\frac{k_i - 1}{2} - \lfloor \frac{k_i}{2} \rfloor) padding=⌊2ki⌋→pi=si×pi+1+(2ki−1−⌊2ki⌋)
当 k i k_i ki为奇数时, ( k i − 1 2 − ⌊ k i 2 ⌋ ) = 0 (\frac{k_i - 1}{2} - \lfloor \frac{k_i}{2} \rfloor) = 0 (2ki−1−⌊2ki⌋)=0,所以 p i = s i ⋅ p i + 1 p_i = s_i \cdot p_{i+1} pi=si⋅pi+1
当 k i k_i ki为偶数时, ( k i − 1 2 − ⌊ k i 2 ⌋ ) = − 0.5 (\frac{k_i - 1}{2} - \lfloor \frac{k_i}{2} \rfloor) = -0.5 (2ki−1−⌊2ki⌋)=−0.5,所以 p i = s i ⋅ p i + 1 − 0.5 p_i = s_i \cdot p_{i+1} - 0.5 pi=si⋅pi+1−0.5
我们的 p i p_i pi是像素块的坐标值,不能取小数,所以基本上可以认为 p i = s i ⋅ p i + 1 p_i = s_i \cdot p_{i+1} pi=si⋅pi+1。
公式得到了极大的化简,得出结论:
感受野中心点的坐标 p i p_i pi只跟前一层 p i + 1 p_{i+1} pi+1有关。
这也是上面一个简单的计算方法。
PPT中的下面的通解,其实就是把公式 p i = s i × p i + 1 + [ ( k i − 1 ) / 2 − p a d d i n g ] p_i=s_i\times p_{i+1}+[(k_i - 1) / 2-padding] pi=si×pi+1+[(ki−1)/2−padding]级联消去整合一下而已,这里不再赘述,感兴趣的同学可以自己手推一下。
SPP-net 是把原始ROI的左上角和右下角 映射到 feature map上的两个对应点。 有了feature map上的两队角点就确定了 对应的 feature map 区域(下图中橙色):
先解释一下两个符号的表示含义:
⌈ ⋅ ⌉ \lceil \cdot \rceil ⌈⋅⌉表示向上取整
⌊ ⋅ ⌋ \lfloor \cdot \rfloor ⌊⋅⌋表示向下取整
左上角的点 ( x , y ) (x,y) (x,y)映射到feature map上的 ( x ′ , y ′ ) (x^{'},y^{'}) (x′,y′),使得: ( x ′ , y ′ ) (x^{'},y^{'}) (x′,y′)在原始图上感受野(上图绿色框的中心点与 ( x , y ) (x,y) (x,y)尽可能接近。
就是前面每层都填 p a d d i n g 2 \frac{padding}{2} 2padding得到的简化公式 :
p i = s i × p i + 1 p_i = s_i \times p_{i+1} pi=si×pi+1
需要把上面公式进行级联得到: p 0 = S × p i + 1 p_0 = S \times p_{i+1} p0=S×pi+1,其中 S = Π 0 i s i S = \Pi_{0}^{i}s_i S=Π0isi
对于feature map 上的 ( x ′ , y ′ ) (x^{'},y^{'}) (x′,y′),它在原始图的对应点为 ( x , y ) = ( S x ′ , S y ′ ) (x,y) = (Sx^{'},Sy^{'}) (x,y)=(Sx′,Sy′)
论文中最后的做法:
把原始图片中的ROI映射为 feature map中的映射区域(上图橙色区域)其中左上角取:
x ′ = ⌊ x S ⌋ + 1 x^{'} = \lfloor \frac{x}{S} \rfloor + 1 x′=⌊Sx⌋+1
y ′ = ⌊ y S ⌋ + 1 y^{'} = \lfloor \frac{y}{S} \rfloor + 1 y′=⌊Sy⌋+1
右下角的点取:
x ′ = ⌊ x S ⌋ − 1 x^{'} = \lfloor \frac{x}{S} \rfloor - 1 x′=⌊Sx⌋−1
y ′ = ⌊ y S ⌋ − 1 y^{'} = \lfloor \frac{y}{S} \rfloor - 1 y′=⌊Sy⌋−1
上图可见:
加1和减1的效果分别是增加和减少。也就是 左上角要向右下偏移,右下角要想要向左上偏移。
个人理解采取这样的策略是因为论文中的映射方法(左上右下映射)会导致feature map上的区域反映射回原始ROI时有多余的区域(下图左边红色框是比蓝色区域大的)