如何计算感受野大小? [关闭]
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。
【讨论】:
以上是关于如何计算感受野大小? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章