CNN中receptive field

昨天鹅厂的电面,敲醒了我,面试后经过一天的失落,最终还是要站起来的,把论文里存在的问题点弄清楚。就从在SPPNet和fast RCNN都涉及到ROI到feature map的映射关系开始吧!

感受野(receptive field):卷积网络中某非输入层的feature map中的神经元(像素点)映射到输入feature map上的区域大小。

是否考虑padding,需要根据具体情况具体分析。首先要注意三个概念:
- 卷积层之间尺寸关系;
- 层间感受野尺寸关系;
- 层间坐标关系;

层间尺寸关系(考虑padding)

输入层->输出层

已知:inputFieldSize:输入层feature map尺寸;
KernelSize:核尺寸;
Padding:单边padding尺寸;
未知:输出层尺寸;
这里写图片描述
其中:

  1. 红色部分:卷积核扫过的像素数,除以stride后,就是对应输出层的像素数;
  2. 绿色部分 :输入层两边各加padding;
  3. 蓝色部分:由于第一步没有考虑最后一个卷积操作,最后的卷积操作对应输出层的最后一个像素

输出层->输入层

已知:otputFieldSize:输出层feature map尺寸;
KernelSize:核尺寸;
Padding:单边padding尺寸;
未知:输入层尺寸(出去padding后的尺寸);
这里写图片描述

  1. 红色部分:先不考虑最后一个像素,其他每个像素对应这输入层的长度。
  2. 绿色部分 :除去padding长度,才是输入层的实际长度。
  3. 蓝色部分:再加上最后一次卷积核的Size,即为输入层的Size。

2 层间感受野尺寸关系(不考虑padding)

根据感受野的定义,表示输出层单位像素点对应输入图像的区域,跟padding无关。只与kernel size和stride有关。
也就是说conv1的feature map的感受野=kernel size,即:上述公式退化成input field size = kernel size(由于padding=0,outputsize=1)

先计算从第i层到第i-1层计算感受野,然后再依次向前计算:

      RF = 1 #待计算的feature map上的感受野大小
  for layer in (top layer To down layer):
    RF = ((RF -1)* stride) + fsize#此处padding区域不考虑,其他和上述公式相同,只是RF刚开始变成1

stride 表示卷积的步长; fsize表示卷积层滤波器的大小
如下图所示:
CNN中receptive field_第1张图片
以下python代码计算Alexnet和VGG16的每层的feature map:

# -*- coding: UTF-8 –*-
import numpy as np

#!/usr/bin/env python

net_struct = {'alexnet': {'net':[[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0]],
                   'name':['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5']},
       'vgg16': {'net':[[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[3,1,1],
                        [2,2,0],[3,1,1],[3,1,1],[3,1,1],[2,2,0],[3,1,1],[3,1,1],[3,1,1],[2,2,0]],
                 'name':['conv1_1','conv1_2','pool1','conv2_1','conv2_2','pool2','conv3_1','conv3_2',
                         'conv3_3', 'pool3','conv4_1','conv4_2','conv4_3','pool4','conv5_1','conv5_2','conv5_3','pool5']},
       'zf-5':{'net': [[7,2,3],[3,2,1],[5,2,2],[3,2,1],[3,1,1],[3,1,1],[3,1,1]],
               'name': ['conv1','pool1','conv2','pool2','conv3','conv4','conv5']}}

imsize = 224

def outFromIn(isz, net, layernum):
    totstride = 1
    insize = isz
    for layer in range(layernum):
        fsize, stride, pad = net[layer]
        outsize = (insize - fsize + 2*pad) / stride + 1
        insize = outsize
        totstride = totstride * stride
    return outsize, totstride

def inFromOut(net, layernum):
    RF = 1
    for layer in reversed(range(layernum)):
        fsize, stride, pad = net[layer]
        RF = ((RF -1)* stride) + fsize
    return RF

if __name__ == '__main__':
    print "layer output sizes given image = %dx%d" % (imsize, imsize)

    for net in net_struct.keys():
        print '************net structrue name is %s**************'% net
        for i in range(len(net_struct[net]['net'])):
            p = outFromIn(imsize,net_struct[net]['net'], i+1)
            rf = inFromOut(net_struct[net]['net'], i+1)
            print "Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (net_struct[net]['name'][i], p[0], p[1], rf)

3 层间坐标关系(考虑左边的padding)

坐标映射关系

由于每层的坐标的原点都是基于当前featuremap在padding前的左上角,如果padding后,图像左上角变化,导致坐标变化,因此,需要最后减去左上角的padding区域。
CNN中receptive field_第2张图片
因此,相邻conv或pooling层的坐标映射关系:这里写图片描述

CNN中receptive field_第3张图片
上图所示:如果每层padding: F/2 ⌊ F / 2 ⌋ ,则feature map的(0,0)点和上一层输入图像的(0,0)点相对应,且feature map的(x,y)点和上一层输入图像的(xS,yS)点相对应。因此,对上面的公式进行简化。
从公式分析: (ki1)2padding=(ki1)2ki2 ( k i − 1 ) 2 − p a d d i n g = ( k i − 1 ) 2 − ⌊ k i 2 ⌋
ki k i 为奇数时, (ki1)2ki2=0 ( k i − 1 ) 2 − ⌊ k i 2 ⌋ = 0
一般卷积核不为偶数,所以上式简化成: pi=sipi1 p i = s i ∗ p i − 1
第i层相对于第1层的stride:strides(i) = stride(1) * stride(2) * …* stride(i-1) (只考虑conv/pooling)
第i层到第1层的坐标映射为: p1=i0sipi p 1 = ∏ 0 i s i ∗ p i

ROI与feature map之间的映射

CNN中receptive field_第4张图片
设:输入图像ROI左上角坐标 (x1,y1) ( x 1 , y 1 ) ,右下角坐标 (x2,y2) ( x 2 , y 2 ) (已知)
feature map的ROI左上角坐标 (x1,y1) ( x 1 ′ , y 1 ′ ) ,右下角坐标 (x2,y2) ( x 2 ′ , y 2 ′ ) (未知)
x1=x1S+1 x 1 ′ = ⌊ x 1 S ⌋ + 1
y1=y1S+1 y 1 ′ = ⌊ y 1 S ⌋ + 1
x2=x2S1 x 2 ′ = ⌈ x 2 S ⌉ − 1
y2=y2S1 y 2 ′ = ⌈ y 2 S ⌉ − 1
为什么加1或减1呢?
看看一下分析:

是否小数 xS x S xS+1 ⌊ x S ⌋ + 1 y2S1 ⌈ y 2 S ⌉ − 1
有小数 1.2 1+1=2(多0.8) 2-1=1(少0.2)
无小数 2 2+1=3(多1) 2-1=1(少1)
- - 总比 xS x S 多0~1 总比 xS x S 少0~1

也就是说左上角坐标反映射到输入图像后,在真实ROI左上角的比较接近右下方,右下角坐标反映射到输入图像后,在真实ROI左上角的比较接近左上方,也就是防止反映射到输入图像的区域超过实际ROI区域。

参考链接

  1. http://www.sohu.com/a/130601394_680233
  2. http://www.cnblogs.com/objectDetect/p/5947169.html

你可能感兴趣的:(DL)