候补:以下介绍的是理论感受野;其实有效感受野因训练方式有关(一般比理论感受野小)
今天看论文时偶然提到了感受野这个名词,这个词在初学卷积神经网络时就已经解除了,但是还没有对其有深入的了解 ,因此在网上百度了一些有关感受野的相关的资料,并自己亲自跑了下计算网络传播过程中感受野大小和feature map大小的代码,感觉理解的更加深入了,下面记录下过程:
这里感谢http://blog.csdn.net/gzq0723/article/details/53138430 博主共享出来的代码!并且本文部分引用了其博文。
以下分三个方面进行整理:
一、感受野的解释
最近在组会讲解框架时,在感受野这个小知识点,大家开始产生歧义,今天我就简单的给大家讲解下这个小知识点,也给初学者带来一个对Receptive Field崭新的认识,如果对只是有深入了解的你,就可以直接跳过O(∩_∩)O~~!
现在开始进入正题!!!
以前我的理解就是,感受野嘛,其实那就是一个视觉感受区域大小。对于单层网络来说,下一层的一个像素点其感受野大小也就是卷积层滤波器的大小,想想其实很明了的就理解了,但对于多层,那就有一点点(也就那么一点点复杂而已)!
正式定义:
在神经网络中,感受野的定义是:
卷积神经网络的每一层输出的特征图(Feature ap)上的像素点在原图像上映射的区域大小。
自己随便画了一个例图,主要看内容,O(∩_∩)O谢谢!
链接: 百度网盘-链接不存在 密码: 2ehd
有读者说有动图就好了,我就截取了一个,请大家欣赏!
现在就开始来说怎么计算吧!(看点来了)其实很简单!
首先可以简单知道(前面也提及到了),第一层卷积层的输出特征图像素的感受野的大小就等于等于卷积层滤波器的大小;然后其继续进行前向传播,这样的话,后面深层的卷积层感受野大小就和之前所有网络层的滤波器大小和步长有关系了,在计算的时候,忽略图像Padding的大小。网络中的每一个层有一个strides,该strides是之前所有层stride的乘积,即:
查资料知,感受野大小的计算采用从深层到前层的方式计算, 即先计算最深层在前一层上的感受野,然后逐渐反馈到第一层,公式具体记如下:
其中V^{‘} {receptive field} 为得的感受野大小, V{receptive field} 为最后层在前一层的感受野大小,Size_{Conv} 为卷积层滤波器大小。
二、相关代码
net_struct = {'alexnet': {'net':[[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0]],
'name':['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5']},
'vgg16': {'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']},
'zf-5':{'net': [[7,2,3],[3,2,1],[5,2,2],[3,2,1],[3,1,1],[3,1,1],[3,1,1]],
'name': ['conv1','pool1','conv2','pool2','conv3','conv4','conv5']}}
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
for layer in reversed(range(layernum)):
fsize, stride, pad = net[layer]
RF = ((RF -1)* stride) + fsize
return RF
if __name__ == '__main__':
print ("layer output sizes given image = %dx%d" % (imsize, imsize))
for net in net_struct.keys():
print ('************net structrue name is %s**************'% net)
for i in range(len(net_struct[net]['net'])):
p = outFromIn(imsize,net_struct[net]['net'], i+1)
rf = inFromOut(net_struct[net]['net'], i+1)
print ("Layer Name = %s, Output size = %3d, Stride = % 3d, RF size = %3d" % (net_struct[net]['name'][i], p[0], p[1], rf))
三、结果截图(在Linux 下Python 2.7.6下运行)