Je lis un article sur l’utilisation de CNN (réseau de neurones convolutifs) pour la détection d’objets.
Hiérarchies de fonctions riches pour une détection d'objet précise et une segmentation sémantique
Voici une citation sur le champ réceptif:
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.
Mes questions sont:
1) C'est la taille de la zone de pixels qui a un impact sur la sortie de la dernière convolution.
2) Pour chaque opération de convolution et de mise en commun, calculez la taille de la sortie. Recherchez maintenant la taille d’entrée qui donne une taille de sortie de 1x1. Thats la taille du champ réceptif
3) Vous n'avez pas besoin d'utiliser une bibliothèque pour le faire. Pour chaque regroupement 2x2, la taille de sortie est réduite de moitié le long de chaque dimension. Pour les convolutions à pas, vous divisez également la taille de chaque dimension par le pas. Vous devrez peut-être réduire une partie de la dimension selon que vous utilisez un rembourrage pour vos circonvolutions. Le cas le plus simple consiste à utiliser padding = floor (taille du noyau/2), de sorte qu'une dose de convolution ne subisse aucun changement supplémentaire dans la taille de la sortie.
Voici une autre façon de calculer le champ réceptif directement. Stackoverflow ne supporte pas les formules mathématiques, pour une version plus lisible, veuillez vous référer à Calcul du champ récepteur de CNN
Le champ réceptif (RF) $ l_k $ de la couche $ k $ est:
$$ l_k = l_ {k-1} + ((f_k - 1) *\prod_ {i = 1} ^ {k-1} s_i) $$
où $ l_ {k-1} $ est le champ de réception de la couche $ k-1 $, $ f_k $ est la taille du filtre .__ (hauteur ou largeur, mais en supposant qu'ils soient identiques ici), et $ s_i $ est la foulée de la couche $ i $.
La formule ci-dessus calcule le champ récepteur de bas en haut (à partir de la couche 1). Intuitivement, RF dans la couche $ k $ couvre $ (f_k - 1) * s_ {k-1} $ plus de pixels Relatif avec la couche $ k-1 $. Cependant, l'incrément doit être traduit dans la première couche .__, de sorte que l'incrément est une factorielle - une foulée dans la couche $ k-1 $ est Exponentiellement plus de foulées dans les couches inférieures.
J'espère que c'est utile.
Comme ci-dessus, avec éventuellement un calcul correct de 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 __== '__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)
Tensorflow prend désormais en charge le calcul de champ réceptif, en utilisant simplement tf.contrib.receptive_field
Voir https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/receptive_field pour plus de détails.
Voici le script python qui calcule la taille RF en plus de la foulée et de la taille de la sortie.
# [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 __== '__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])
Supposons que nous ayons une architecture de réseau qui only se compose de plusieurs couches de convolution. Pour chaque couche de convolution, nous définissons une taille de noyau carrée et un taux de dilatation. En outre, supposons que la foulée soit égale à 1. Vous pouvez donc calculer le champ récepteur du réseau à l'aide du code python suivant:
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)
Par exemple, calculons le champ réceptif (RF) du DnCNN (réseau neuronal convolutionnel dénoisant) bien connu [1] . Utilisez le code ci-dessus avec les entrées suivantes pour calculer le RF de ce réseau. (vous obtiendrez RF = 35).
# In DnCNN-S, the network has 17 convolution layers.
K=[3]*17 # Kernel Size
R=[1]*17 # Dilation Rate
[1] Zhang, Kai et al. "Au-delà d'un dénoiseur gaussien: Apprentissage résiduel de CNN en profondeur pour le débruitage d'image." Transactions IEEE sur le traitement d'images 26.7 (2017): 3142-3155.