卷積神經網絡物體檢測之感受野大小計算

原文鏈接:https://www.cnblogs.com/objectDetect/p/5947169.html

學習RCNN系列論文時, 出現了感受野(receptive field)的名詞, 感受野的尺寸大小是如何計算的,在網上沒有搜到特別詳細的介紹, 爲了加深印象,記錄下自己對這一感念的理解,希望對理解基於CNN的物體檢測過程有所幫助。

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)
        

 

reference

https://www.cnblogs.com/objectDetect/p/5947169.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章