CV/DL基础知识 之 卷积网络感受野计算公式推导
CV/DL基础知识 之 卷积网络感受野计算公式推导
首先解释一下什么是感受野:
假设将原始输入(一般是图像)img输入到网络中,某卷积层layer_i输出的特征图为map_i。map_i的感受野就是map_i中的某个元素在这个计算过程中涉及到的img的元素数量。
我们一步步来。
符号标记:
除了上面用到的符号,我们用
r_i表示map_i的感受野尺寸;
k_i、s_i表示layer_i的卷积核尺寸、步长;
如图1,2所示:
图1:
图2:
我们首先计算r_1:
如图2,map_1的蓝色元素,
map_1中的每个元素都是由原图img中k_1个相邻元素计算来的,所以:
r_1 = k_1 (1)
然后是r_2:
同样,map_2中的每个元素涉及到map_1中k_2个相邻元素,但是这k_2个元素是相邻的,当s_1<k_1时,它们的感受野(在img上涉及的元素)是互有重叠的,如图2中三个矩形框互相重叠,所以不能直接用k_2*k_1来计算r_2。
但是从图2上可以看出,r_2覆盖的img的元素个数正好是(k_2 - 1)个s_1再加上k_1,即:
r_2 = (k_2 - 1)*s_1 + k_1 (2)
这里要说明一点:当s_1>k_1,map_1中k_2个相邻元素的感受野之间不仅没有重叠,而且有间隙,但这是我们认为这些间隙也算作r_2的一部分。
然后是r_3:
直接计算map_3和img之间的关联是困难的,不信你可以试试。我们能够直接计算是相邻两层,比如,map_3中的一个元素关联着map_2中的k_3个元素。这是因为相邻两层,只涉及一个卷积核(map_3中的一个元素只涉及一个卷积核k_3覆盖的map_2中的元素),因此不存在步长、重叠的问题。
当我们计算相邻的三层卷积层时,覆盖和步长带来的感受野变化这个问题就出现了,但由于3层只涉及一次覆盖和步长,我们仍然可以直接写出一个公式,就像我们刚刚计算r_2那样。
因此,当我们要计算r_3,这涉及2次覆盖和步长,我们(我)无法直接写出公式。于是我们先根据r_2的计算,得到map_3和map_1的元素关联。这可以直接用r_2的结论,map_3中的一个元素 涉及到 map_1中的 (k_3 - 1)*s_2 + k_2个元素。没有理解的同学可以回去看一下图2,把图中的map_2看作我们这里的map_3,img看作我们这里的map_1。
强调一下,我们有了map_3和map_1的元素关联,而且显然的是,map_3中的一个元素 涉及到 的map_1中的元素是相邻的,即:我们知道*map_3中的一个元素涉及到了 map_1中的 (k_3 - 1)s_2 + k_2个相邻的元素。
那如何知道map_1和img的关系呢?
现在,我们再此审视一下公式(2),回忆一下公式(2)中的k_2是什么意思?是layer2的卷积核?是的。为什么layer2的卷积核会出现在公式(2)中呢,因为它的含义是:map_2中的每个元素涉及到map_1中k_2个相邻元素。而我们现在知道了*map_3中的一个元素涉及到了 map_1中的 (k_3 - 1)s_2 + k_2个相邻的元素,那岂不是将 (k_3 - 1)*s_2 + k_2替换调公式(2)中的k_2,就能得到r_3了?
是的:
r_3 = (((k_3 - 1)*s_2 + k_2) - 1)*s_1 + k_1 (3)
很显然,我们可以通过计算map_4和map_2的关系,得到:map_3中的一个元素涉及到了 map_2中的 (k_4 - 1)*s_3 + k_3个相邻的元素,然后将 (k_4 - 1)*s_3 + k_3替换(3)中的k_3,获得r_4,以此类推,可以得到任何r_i
但是,如果i比较大的话,那计算r_i的公式未免也有点太长了吧。能不能化简一下呢?
很显然,r_i必然和layer_i之前的所有层都有关系,也就是说r_i的计算必然牵扯到之前所有卷积层的参数,正如同我们目前已有的这个复杂公式一样。
那么,一个直观的化简思路就是,用计算 之前特征图的感受野 的中间结果,来代替layer_i之前的层的某些参数:若干s和若干k中的至少一个。
沿着这个思路,下面我们用r_3和r_2来推导。
联立(2)(3),消去其中的k_1(你也可以消去s_1试试),得到:
r_3 = (k_3 - 1)*s_2 *s_1 + r_1 (4)
化简结果比我们想象的好,不只是消去了k_1,而是消去了所有的k参数。
那么:
r_i = (k_i - 1)*s_i *s_(i-1)*...*s_1 + r_(i-1) 对于i>=2 (5)
r_i = k_i 对于i=1
这就简单多了吧。
当然,我们可以进一步把公式(5)中i=1的情况统一到i>=2的形式中,只需要我们定义:img的感受野r_0=1,补偿s_0=1。
就有:
r_i = (k_i - 1)*s_i *s_(i-1)*...*s_1 + r_(i-1) (6)
完结。