深度學習:卷積神經網路物體檢測之感受野大小計算
1 感受野的概念
在卷積神經網路中,感受野的定義是 卷積神經網路每一層輸出的特徵圖(feature map)上的畫素點在原始影象上對映的區域大小。
RCNN論文中有一段描述,Alexnet網路pool5輸出的特徵圖上的畫素在輸入影象上有很大的感受野(have very large receptive fields (195 × 195 pixels))和步長(strides (32×32 pixels) ), 這兩個變數的數值是如何得出的呢?
2 感受野大小的計算
感受野計算時有下面的幾個情況需要說明:
(1)第一層卷積層的輸出特徵影象素的感受野的大小等於濾波器的大小
(2)深層卷積層的感受野大小和它之前所有層的濾波器大小和步長有關係
(3)計算感受野大小時,忽略了影象邊緣的影響,即不考慮padding的大小,關於這個疑惑大家可以閱讀一下參考文章2的解答進行理解
這裡的每一個卷積層還有一個strides的概念,這個strides是之前所有層stride的乘積。
即: strides(i) = stride(1) * stride(2) * …* stride(i-1)
關於感受野大小的計算採用 top to down 的方式, 即先計算最深層在前一層上的感受野,然後逐漸傳遞到第一層,使用的公式可以表示如下:
RF = 1 #待計算的feature map上的感受野大小
for layer in (top layer To down layer):
RF = ((RF -1)* stride) + fsize
stride 表示卷積的步長; fsize表示卷積層濾波器的大小
用python實現了計算Alexnet zf-5和VGG16網路每層輸出feature map的感受野大小,實現程式碼:
#!/usr/bin/env python
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)
receptiveField.py
執行後的結果如下:
4 Convolutional Feature Maps: Elements of Efficient (and Accurate) CNN-based Object Detection
5 Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition