Как рассчитать размер приемного поля?

Я читаю статью об использовании 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

1) Это размер области пикселей, которая влияет на результат последней свертки.

2) Для каждой операции свертки и объединения, вычислите размер вывода. Теперь найдите размер ввода, который приведет к размеру вывода 1x1. Это размер восприимчивого поля

3) Для этого вам не нужно использовать библиотеку. Для каждого объединения 2x2 выходной размер уменьшается на половину по каждому измерению. Для чередующихся сверток вы также разделяете размер каждого измерения по шагу. Возможно, вам придется сбрить часть измерения в зависимости от того, используете ли вы прописку для своих сверток. Простейшим случаем является использование padding = floor (размер ядра /2), так что доза свертки не будет иметь никаких дополнительных изменений размера вывода.

Ответ 2

Вот еще один способ вычислить рецептивное поле напрямую. Stackoverflow не поддерживает математическую формулу, для более читаемой версии, пожалуйста, обратитесь к Расчету Восприимчивого поля CNN

Рецептивное поле (RF) $ l_k $ слоя $ 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 $ - шаг слой $ я $.

Формула выше вычисляет рецептивное поле снизу вверх (от слоя 1). Интуитивно понятно, что RF в слое $ k $ покрывает на $ (f_k - 1) * s_ {k-1} $ больше пикселей относительно слоя $ k-1 $. Однако приращение необходимо преобразовать в первый уровень, поэтому приращения являются факториальными - шаг в слое $ k-1 $ экспоненциально больше шагов в нижних слоях.

Надеюсь, это полезно.

Ответ 4

Как и выше, с возможным правильным вычислением 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)

Ответ 5

Здесь python script, который вычисляет размер 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])

Ответ 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)

В качестве примера, давайте вычислим рецептивное поле (RF) хорошо известного DnCNN (шумоподавляющая сверточная нейронная сеть) [1]. Используйте приведенный выше фрагмент кода со следующими входами для вычисления 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.