如何计算感受野大小? [关闭]

Posted

技术标签:

【中文标题】如何计算感受野大小? [关闭]【英文标题】:How to calculate receptive field size? [closed] 【发布时间】:2016-06-05 14:01:05 【问题描述】:

我正在阅读有关使用 CNN(卷积神经网络)进行对象检测的论文。

Rich feature hierarchies for accurate object detection and semantic segmentation

这是关于感受野的引述:

The pool5 feature map is 6x6x256 = 9216 dimensional. Ignoring boundary effects, each pool5 unit has a receptive field of 195x195 pixels in the original 227x227 pixel input. A central pool5 unit has a nearly global view,
while one near the edge has a smaller, clipped support.

我的问题是:

    感受野的定义是什么? 他们如何计算感受野的大小和位置? 我们如何使用 caffe/pycaffe 计算感受野的边界矩形?

【问题讨论】:

这里有一个感受野在线计算器:fomoro.com/tools/receptive-fields rubikscode.net/2020/05/18/… 了解计算背后的数学的好资源 【参考方案1】:

1) 影响最后一个卷积输出的像素区域的大小。

2) 对于每个卷积和池化操作,计算输出的大小。现在找到导致输出大小为 1x1 的输入大小。这就是感受野的大小

3) 您不需要使用库来执行此操作。对于每 2x2 池化,输出大小沿每个维度减少一半。对于跨步卷积,您还可以将每个维度的大小除以步幅。根据您是否对卷积使用填充,您可能需要削减一些尺寸。最简单的情况是使用 padding = floor(kernel size/2),这样卷积不会对输出大小产生任何额外的变化。

【讨论】:

【参考方案2】:

这是计算除步幅和输出大小之外的 RF 大小的 Python 脚本。

    # [filter size, stride, padding]

convnet =[[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0],[6,1,0]]
layer_name = ['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5','fc6-conv']
imsize = 227


def outFromIn(isz, layernum = 9, net = convnet):
    if layernum>len(net): layernum=len(net)

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

    RFsize = isz - (outsize - 1) * totstride

    return outsize, totstride, RFsize

if __name__ == '__main__':

    print "layer output sizes given image = %dx%d" % (imsize, imsize)
    for i in range(len(convnet)):
        p = outFromIn(imsize,i+1)
        print "Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (layer_name[i], p[0], p[1], p[2])

【讨论】:

我认为是错误的。 哪一部分?请具体点。如果有任何错误报告,我将不胜感激【参考方案3】:

如上所述,RF 的计算可能正确:

#Compute input size that leads to a 1x1 output size, among other things   

# [filter size, stride, padding]

convnet =[[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0],[6,1,0]]
layer_name = ['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5','fc6-conv']
imsize = 227

def outFromIn(isz, layernum = 9, net = convnet):
    if layernum>len(net): layernum=len(net)

    totstride = 1
    insize = isz
    #for layerparams in net:
    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( layernum = 9, net = convnet):
    if layernum>len(net): layernum=len(net)
    outsize = 1
    #for layerparams in net:
    for layer in reversed(range(layernum)):
        fsize, stride, pad = net[layer]
        outsize = ((outsize -1)* stride) + fsize
    RFsize = outsize
    return RFsize

if __name__ == '__main__':

    print "layer output sizes given image = %dx%d" % (imsize, imsize)
    for i in range(len(convnet)):
        p = outFromIn(imsize,i+1)
        rf = inFromOut(i+1)
        print "Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (layer_name[i], p[0], p[1], rf)

【讨论】:

【参考方案4】:

这是另一种直接计算感受野的方法。 *** 不支持数学公式,更易读的版本请参考Calculating Receptive Field of CNN

层$k$的感受野(RF)$l_k$是:

$$ l_k = l_k-1 + ((f_k - 1) * \prod_i=1^k-1s_i) $$

其中 $l_k-1$ 是层 $k-1$ 的感受野,$f_k$ 是过滤器大小 (高度或宽度,但假设它们在这里相同),$s_i$ 是步幅 层$i$。

上面的公式从下往上计算感受野(从层 1)。直观地说,$k$ 层中的 RF 覆盖了 $(f_k - 1) * s_k-1$ 个像素 相对于层 $k-1$。但是,增量需要转换为 第一层,所以增量是阶乘 --- $k-1$ 层的步幅是 低层的步幅呈指数级增长。

希望这有帮助。

【讨论】:

链接失效 感谢您的指出。它现在应该可以工作了。【参考方案5】:

2019 年 12 月 11 日更新:

TF 库已移至https://github.com/google-research/receptive_field

另请参阅 Distill 论文“计算卷积神经网络的接收域”:https://distill.pub/2019/computing-receptive-fields/

旧:

Tensorflow 现在支持接受域计算,只需使用 tf.contrib.receptive_field

详情请见https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/receptive_field。

【讨论】:

这个页面已经不存在了,我猜当前链接是你的:github.com/google-research/receptive_field 顺便说一句,我在这里问与 GH (github.com/google-research/receptive_field/issues/1) 相同的问题,有没有办法让它与 tensorflow.keras 一起工作? 让我直接在github上回复,所以我们不重复讨论:)【参考方案6】:

假设我们有一个由多个卷积层组成的网络架构。对于每个卷积层,我们定义了一个方形内核大小和一个膨胀率。另外,假设步长为 1。因此,您可以通过以下 python 代码计算网络的感受野:

K=[3,3]   # Kernel Size
R=[1,2]  # Dilation Rate

RF=1
d=1 # Depth
for k,r in zip(K,R):
    support=k+(k-1)*(r-1) # r-dilated conv. adds r-1 zeros among coefficients
    RF=support+(RF-1)
    print('depth=%d, K=%d, R=%d, kernel support=%d'%(d,k,r,support))
    d=d+1
print('Receptive Field: %d'%RF)

作为一个例子,让我们计算著名的 DnCNN(去噪卷积神经网络)[1] 的感受野 (RF)。 使用上面的代码和以下输入来计算该网络的 RF。 (你会得到 RF=35)。

# In DnCNN-S, the network has 17 convolution layers.
K=[3]*17  # Kernel Size
R=[1]*17  # Dilation Rate

[1] 张凯,等。 “超越高斯去噪器:深度 cnn 的残差学习用于图像去噪。” IEEE 图像处理汇刊 26.7 (2017): 3142-3155。

【讨论】:

以上是关于如何计算感受野大小? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

深度学习笔记感受野计算

CNN中感受野(Receptive Field)的计算和理解

感受野

关于感受野的理解与计算

CNN中感受野的计算

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