web-dev-qa-db-ja.com

受容野サイズを計算する方法は?

私はCNN(畳み込みニューラルネットワーク)をオブジェクト検出に使用することについての論文を読んでいます。

正確なオブジェクト検出とセマンティックセグメンテーションのための豊富な機能階層

これは受容野についての引用です:

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.

私の質問は:

  1. 受容野の定義とは?
  2. 彼らはどのように受容野のサイズと位置を計算しますか?
  3. Caffe/pycaffeを使用して受容野の境界矩形をどのように計算できますか?
17
mrgloom

1)最後の畳み込みの出力に影響を与えるのは、ピクセル領域のサイズです。

2)たたみ込みとプーリング操作ごとに、出力のサイズを計算します。次に、出力サイズが1x1になる入力サイズを見つけます。それは受容野の大きさです

3)ライブラリを使用する必要はありません。 2x2のプールごとに、出力サイズは各次元に沿って半分になります。ストライドコンボリューションの場合、各次元のサイズをストライドで除算することもできます。たたみ込みにパディングを使用するかどうかによっては、一部の次元を削る必要がある場合があります。最も単純なケースは、padding = floor(kernel size/2)を使用することです。これにより、たたみ込みは出力サイズに余分な変更を加えません。

7
Raff.Edward

これは、受容野を直接計算する別の方法です。 Stackoverflowは数式をサポートしていません。より読みやすいバージョンについては、 CNNの受容フィールドの計算 を参照してください。

層$ k $の受容野(RF)$ l_k $は次のとおりです。

$$ l_k = l_ {k-1} +((f_k-1)*\prod_ {i = 1} ^ {k-1} s_i)$$

ここで、$ l_ {k-1} $はレイヤー$ k-1 $の受容フィールド、$ f_k $はフィルターサイズ(高さまたは幅ですが、ここでは同じであると想定)、$ s_i $はレイヤー$ i $。

上記の式は、下から上に(レイヤー1から)受容野を計算します。直感的に、RFレイヤー$ k $は$(f_k-1)* s_ {k-1} $レイヤー$ k-1 $に比べてより多くのピクセルをカバーします。ただし、増分は最初のレイヤーに変換されるので、増分は階乗です---レイヤー$ k-1 $のストライドは、下のレイヤーの指数関数的にストライドです。

これがお役に立てば幸いです。

7
Shawn Lee

2019年12月11日更新:

TFライブラリは https://github.com/google-research/receptive_field に移動されました

Distillの論文「Compvolutioning Receptive Fields of Convolutional Neural Networks」もご覧ください: https://distill.pub/2019/computing-receptive-fields/

古い:

Tensorflowは、tf.contrib.receptive_fieldを使用するだけで、受容野の計算をサポートするようになりました

詳細は https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/receptive_field を参照してください。

6
André Araujo

上記のように、おそらく正しい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
Dushyant Mehta

ストライドと出力のサイズに加えてpythonサイズを計算するRFスクリプトです。

    # [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])
2
GieBur

onlyが複数の畳み込み層で構成されるネットワークアーキテクチャがあるとします。畳み込み層ごとに、正方形のカーネルサイズと膨張率を定義します。また、ストライドが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] Zhang、Kai、等。 「ガウス雑音除去器を超えて:画像雑音除去のためのディープcnnの残留学習。」 IEEE Transactions on Image Processing 26.7(2017):3142-3155。

0
ashkan