卷积神经网络感受野的计算

学习RCNN系列论文时, 出现了感受野(receptive field)的名词, 感受野的尺寸大小是如何计算的,在网上没有搜到特别详细的介绍, 为了加深印象,记录下自己对这一感念的理解,希望对理解基于CNN的物体检测过程有所帮助。

1 感受野的概念

  在卷积神经网络中,感受野的定义是 卷积神经网络每一层输出的特征图(feature map)上的像素点在原始图像上映射的区域大小。

  

  RCNN论文中有一段描述,Alexnet网络pool5输出的特征图上的像素在输入图像上有很大的感受野(have very large receptive fields (195 × 195 pixels))和步长(strides (32×32 pixels) ), 这两个变量的数值是如何得出的呢?

2 感受野大小的计算

 感受野计算时有下面的几个情况需要说明:

  (1)第一层卷积层的输出特征图像素的感受野的大小等于滤波器的大小

  (2)深层卷积层的感受野大小和它之前所有层的滤波器大小和步长有关系

  (3)计算感受野大小时,忽略了图像边缘的影响,即不考虑padding的大小,关于这个疑惑大家可以阅读一下参考文章2的解答进行理解

这里的每一个卷积层还有一个strides的概念,这个strides是之前所有层stride的乘积。  

  即strides(i) = stride(1) * stride(2) * ...* stride(i-1) 

  关于感受野大小的计算采用top to down的方式, 即先计算最深层在前一层上的感受野,然后逐渐传递到第一层,使用的公式可以表示如下:   

       RF = 1 #待计算的feature map上的感受野大小
  for layer in (top layer To down layer):
    RF = ((RF -1)* stride) + fsize

stride 表示卷积的步长; fsize表示卷积层滤波器的大小  

用python实现了计算VGG16网络每层输出feature map的感受野大小,实现代码:

#!/usr/bin/env python


net = {'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']}

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   # 最后一层相对前一层的感受野是1
    for layer in reversed(range(layernum)):    # 从最后一层往前数
        t = RF
        fsize, stride, pad = net[layer]        # 得到这一层的fsize,stride,pad
        RF = ((RF - 1) * stride) + fsize       # 最后
        # print(t,stride, fsize,  RF)
    return RF


if __name__ == '__main__':
    for i in range(len(net['net'])):    # 逐层进行处理
        p = outFromIn(imsize, net['net'], i + 1)    # 得到当前层的输出信息
        # print(p[0], p[1])
        # if i != 5:
        #     continue
        rf = inFromOut(net['net'], i + 1)
        # print(rf, '**')
        print("Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (
            net['name'][i], p[0], p[1], rf))

假如要计算第N层的感受野,总的计算过程就是:从后往前计算,也就是第N层相对前面层的感受野(即第N-1层到第1层)。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值