彻底搞懂感受野的含义与计算


博客:博客园 | **** | blog

什么是感受野

The receptive field is defined as the region in the input space that a particular CNN’s feature is looking at (i.e. be affected by).

—— A guide to receptive field arithmetic for Convolutional Neural Networks

感受野(Receptive Field),指的是神经网络中神经元“看到的”输入区域,在卷积神经网络中,feature map上某个元素的计算受输入图像上某个区域的影响,这个区域即该元素的感受野。

卷积神经网络中,越深层的神经元看到的输入区域越大,如下图所示,kernel size 均为3×33 \times 3,stride均为1,绿色标记的是Layer2Layer 2 每个神经元看到的区域,黄色标记的是Layer3Layer 3 看到的区域,具体地,Layer2Layer 2每个神经元可看到Layer1Layer 13×33 \times 3 大小的区域,Layer3Layer3 每个神经元看到Layer2Layer 23×33 \times 3 大小的区域,该区域可以又看到Layer1Layer 15×55 \times 5 大小的区域。

彻底搞懂感受野的含义与计算

所以,感受野是个相对概念,某层feature map上的元素看到前面不同层上的区域范围是不同的,通常在不特殊指定的情况下,感受野指的是看到输入图像上的区域。

为了具体计算感受野,这里借鉴视觉系统中的概念,
receptive field=center+surround receptive \ field = center + surround

准确计算感受野,需要回答两个子问,即视野中心在哪和视野范围多大

  • 只有看到”合适范围的信息”才可能做出正确的判断,否则就可能“盲人摸象”或者“一览众山小”;
  • 目标识别问题中,我们需要知道神经元看到是哪个区域,才能合理推断物体在哪以及判断是什么物体。

但是,网络架构多种多样,每层的参数配置也不尽相同,感受野具体该怎么计算?

约定

在正式计算之前,先对数学符号做如下约定,

彻底搞懂感受野的含义与计算

  • kk:kernel size

  • pp:padding size

  • ss:stride size

  • LayerLayer:用LayerLayer表示feature map,特别地 Layer 0Layer \ 0为输入图像;

  • ConvConv:用ConvConv表示卷积,kkppss为卷积层的超参数,Conv lConv \ l的输入和输出分别为 Layer l1Layer \ l-1Layer l+1Layer \ l+1

  • nn:feature map size为 n×nn \times n,这里假定height=widthheight = width

  • rr:receptive field size为r×rr \times r,这里假定感受野为方形;

  • jj:feature map上相邻元素间的像素距离,即将feature map上的元素与输入图像Layer 0Layer \ 0 上感受野的中心对齐后,相邻元素在输入图像上的像素距离,也可以理解为 feature map上前进1步相当于输入图像上前进多少个像素,如下图所示,feature map上前进1步,相当于输入图像上前进2个像素,j=2j=2

    彻底搞懂感受野的含义与计算

  • startstart:feature map左上角元素在输入图像上的感受野中心坐标(start,start)(start, start),即视野中心的坐标,在上图中,左上角绿色块感受野中心坐标为(0.5,0.5)(0.5, 0.5),即左上角蓝色块中心的坐标,左上角白色虚线块中心的坐标为(0.5,0.5)(-0.5, -0.5)

  • llll表示层,卷积层为Conv lConv \ l,其输入feature map为Layer l1Layer \ l-1,输出为Layer lLayer \ l

下面假定所有层均为卷积层。

感受野大小

感受野大小的计算是个递推公式。

再看上面的动图,如果feature map $Layer \ 2 $ 上的一个元素AA看到feature map Layer 1Layer \ 1 上的范围为3×33 \times 3(图中绿色块),其大小等于kernel size k2k_2,所以,AA看到的感受野范围r2r_2等价于Layer 1Layer \ 13×33 \times 3窗口看到的Layer 0Layer \ 0 范围,据此可以建立起相邻LayerLayer感受野的关系,如下所示,其中rlr_{l}Layer lLayer \ l的感受野,rl1r_{l-1}Layer l1Layer \ l-1 的感受野,
rl=rl1+(kl1)jl1 r_{l} = r_{l-1} + (k_{l} - 1) * j_{l-1}

  • Layer lLayer \ l 一个元素的感受野rlr_{l}等价于Layer l1Layer \ l-1k×kk \times k 个感受野的叠加;
  • Layer l1Layer \ l-1 上一个元素的感受野为rl1r_{l-1}
  • Layer l1Layer \ l-1 上连续kk 个元素的感受野可以看成是,第1个元素看到的感受野加上剩余k1k-1步扫过的范围Layer l1Layer \ l-1 上每前进1个元素相当于在输入图像上前进jl1j_{l-1}个像素,结果等于rl1+(k1)×jl1r_{l-1} + (k - 1) \times j_{l-1}

可视化如下图所示,

彻底搞懂感受野的含义与计算

下面的问题是,jinj_{in}怎么求?

Layer lLayer \ l 上前进1个元素相当于Layer l1Layer \ l-1上前进sls_l个元素,转换成像素单位为
jl=jl1×sl j_{l} = j_{l-1} \times s_{l}
其中,sls_lConv lConv \ l的kernel在Layer l1Layer \ l-1 上滑动的步长,输入图像的s0=1s_0 = 1

根据递推公式可知,
jl=i=1lsi \begin{aligned} j_l &= \prod_{i=1}^{l} s_{i}\\ \end{aligned}
Layer lLayer \ l上前进1个元素,相当于在输入图像前进了i=1lsi\prod_{i=1}^{l} s_{i}个像素,即前面所有层stridestride的连乘。

进一步可得,Layer lLayer \ l的感受野大小为
rl=rl1+(kl1)jl1=rl1+((kl1)i=1l1si) \begin{aligned} r_{l} &= r_{l-1} + \left(k_{l}-1\right) * j_{l-1} \\ &= r_{l-1}+\left(\left(k_{l}-1\right) * \prod_{i=1}^{l-1} s_{i}\right) \end{aligned}

感受野中心

感受野中心的计算也是个递推公式。

在上一节中计算得jl=i=1lsij_l = \prod_{i=1}^{l} s_{i},表示**feature map Layer lLayer \ l上前进1个元素相当于在输入图像上前进的像素数目,如果将feature map上元素与感受野中心对齐,则jlj_l为感受野中心之间的像素距离。**如下图所示,

彻底搞懂感受野的含义与计算

其中,各层的kernel size、padding、stride超参数已在图中标出,右侧图为feature map和感受野中心对齐后的结果。

相邻LayerLayer间,感受野中心的关系为
startl=startl1+(kl12pl)jl1 start_{l} = start_{l-1} + (\frac{k_l - 1}{2} - p_l) * j_{l-1}
所有的startstart坐标均相对于输入图像坐标系。其中,start0=(0.5,0.5)start_0=(0.5,0.5),为输入图像左上角像素的中心坐标,startl1start_{l-1}表示Layer l1Layer \ l-1左上角元素的感受野中心坐标,(kl12pl)(\frac{k_l - 1}{2} - p_l)Layer lLayer \ lLayer l1Layer \ l-1感受野中心相对于Layer l1Layer \ l-1坐标系的偏差,该偏差需折算到输入图像坐标系,其值需要乘上jl1j_{l-1},即Layer l1Layer \ l-1相邻元素间的像素距离,相乘的结果为(kl12pl)jl1(\frac{k_l - 1}{2} - p_l) * j_{l-1},即感受野中心间的像素距离——相对输入图像坐标系。至此,相邻LayerLayer间感受野中心坐标间的关系就不难得出了,这个过程可视化如下。

彻底搞懂感受野的含义与计算

知道了Layer lLayer \ l左上角元素的感受野中心坐标(startl,startl)(start_l, start_l),通过该层相邻元素间的像素距离jlj_l可以推算其他元素的感受野中心坐标。

小结

将感受野的相关计算小结一下,
jl=jl1×sljl=i=1lsirl=rl1+(kl1)jl1=rl1+((kl1)i=1l1si)startl=startl1+(kl12pl)jl1 \begin{aligned} j_{l} &= j_{l-1} \times s_{l} \\ j_l &= \prod_{i=1}^{l} s_{i}\\ r_{l} &= r_{l-1} + \left(k_{l}-1\right) * j_{l-1} \\ &= r_{l-1}+\left(\left(k_{l}-1\right) * \prod_{i=1}^{l-1} s_{i}\right) \\ start_{l} &= start_{l-1} + (\frac{k_l - 1}{2} - p_l) * j_{l-1} \end{aligned}
由上面的递推公式,就可以从前向后逐层计算感受野了,代码可参见computeReceptiveField.py,在线可视化计算可参见Receptive Field Calculator

最后,还有几点需要注意,

  • Layer lLayer \ l的感受野大小与sls_lplp_l无关,即当前feature map元素的感受野大小与该层相邻元素间的像素距离无关;
  • 为了简化,通常将padding size设置为kernel的半径,即p=k12p = \frac{k-1}{2},可得startl=startl1start_l = start_{l-1},使得feature map Layer lLayer \ l(x,y)(x, y)位置的元素,其感受野中心坐标为(xjl,yjl)(x j_l, y j_l)
  • 对于空洞卷积dilated convolution,相当于改变了卷积核的尺寸,若含有dilation ratedilation\ rate参数,只需将klk_l替换为dilation rate(kl1)+1dilation \ rate * (k_l - 1) + 1dilation rate=1dilation\ rate=1时为正常卷积;
  • 对于pooling层,可将其当成特殊的卷积层,同样存在kernel size、padding、stride参数;
  • 非线性**层为逐元素操作,不改变感受野。

以上。

参考