2016-02-23 10 views
8

Sto leggendo articoli sull'utilizzo della CNN (rete neurale convolutional) per il rilevamento di oggetti.Come calcolare la dimensione del campo ricettivo?

Rich feature hierarchies for accurate object detection and semantic segmentation

Ecco una citazione su campo recettivo:

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. 

Le mie domande sono:

  1. Qual è la definizione di campo recettivo?
  2. Come vengono calcolate le dimensioni e la posizione del campo recettivo?
  3. Come possiamo calcolare il limite di ricezione del campo utilizzando caffe/pycaffe?

risposta

5

1) È la dimensione dell'area dei pixel che influisce sull'uscita dell'ultima convoluzione.

2) Per ciascuna operazione di convoluzione e raggruppamento, calcolare la dimensione dell'uscita. Ora trova la dimensione di input che risulta in una dimensione di output di 1x1. Questa è la dimensione del campo recettivo

3) Non è necessario utilizzare una libreria per farlo. Per ogni pool 2x2, le dimensioni dell'output sono ridotte della metà lungo ciascuna dimensione. Per le increspate circonvoluzioni, si divide anche la dimensione di ciascuna dimensione per la falcata. Potrebbe essere necessario rimuovere alcune dimensioni a seconda se si utilizza il riempimento per le circonvoluzioni. Il caso più semplice è usare padding = floor (dimensione del kernel/2), in modo che una dose di convoluzione non abbia alcun cambiamento aggiuntivo sulla dimensione dell'output.

2

Ecco lo script python che calcola la dimensione RF oltre al passo e alla dimensione dell'output.

# [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]) 
+1

Penso che sia sbagliato. –

+0

quale parte? Per favore, sii specifico. Gradirei una segnalazione di bug se ce ne sono – GieBur

4

Come sopra, con eventualmente calcolo corretto 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) 
3

Ecco un altro modo per calcola direttamente campo recettivo. StackOverflow non supporta formula matematica, per una versione più leggibile, si prega di fare riferimento a http://shawnleezx.github.io/blog/2017/02/11/calculating-receptive-field-of-cnn/

Il campo recettivo (RF) $ l_k $ dello strato di $ k $ è:

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

dove $ l_ {K- 1} $ è il campo ricettivo del layer $ k-1 $, $ f_k $ è la dimensione del filtro (altezza o larghezza, ma supponendo che siano gli stessi qui), e $ s_i $ è il passo del livello $ i $ .

La formula sopra calcola il campo ricettivo dal basso verso l'alto (dal livello 1). Intuitivamente, RF nel layer $ k $ copre $ (f_k - 1) * s_ {k-1} $ più pixel relativi al layer $ k-1 $. Tuttavia, l'incremento deve essere tradotto nel primo livello , quindi gli incrementi sono fattoriali --- una graduazione nel livello $ k-1 $ è esponenzialmente più passi nei livelli inferiori.

Spero che questo sia utile.