85 votes

Comment calculer le nombre de paramètres d'un réseau de neurones convolutifs ?

J'utilise Lasagne pour créer un CNN pour le jeu de données MNIST. Je suis de près cet exemple : Réseaux neuronaux convolutifs et extraction de caractéristiques avec Python .

L'architecture CNN que j'ai pour l'instant, qui n'inclut pas de couches d'exclusion, est la suivante :

NeuralNet(
    layers=[('input', layers.InputLayer),        # Input Layer
            ('conv2d1', layers.Conv2DLayer),     # Convolutional Layer
            ('maxpool1', layers.MaxPool2DLayer), # 2D Max Pooling Layer
            ('conv2d2', layers.Conv2DLayer),     # Convolutional Layer
            ('maxpool2', layers.MaxPool2DLayer), # 2D Max Pooling Layer
            ('dense', layers.DenseLayer),        # Fully connected layer
            ('output', layers.DenseLayer),       # Output Layer
            ],
    # input layer
    input_shape=(None, 1, 28, 28),

    # layer conv2d1
    conv2d1_num_filters=32,
    conv2d1_filter_size=(5, 5),
    conv2d1_nonlinearity=lasagne.nonlinearities.rectify,

    # layer maxpool1
    maxpool1_pool_size=(2, 2),

    # layer conv2d2
    conv2d2_num_filters=32,
    conv2d2_filter_size=(3, 3),
    conv2d2_nonlinearity=lasagne.nonlinearities.rectify,

    # layer maxpool2
    maxpool2_pool_size=(2, 2),

    # Fully Connected Layer
    dense_num_units=256,
    dense_nonlinearity=lasagne.nonlinearities.rectify,

   # output Layer
    output_nonlinearity=lasagne.nonlinearities.softmax,
    output_num_units=10,

    # optimization method params
    update= momentum,
    update_learning_rate=0.01,
    update_momentum=0.9,
    max_epochs=10,
    verbose=1,
    )

Cela produit les informations suivantes sur les couches :

  #  name      size
---  --------  --------
  0  input     1x28x28
  1  conv2d1   32x24x24
  2  maxpool1  32x12x12
  3  conv2d2   32x10x10
  4  maxpool2  32x5x5
  5  dense     256
  6  output    10

et sort le nombre de paramètres apprenables comme 217,706

Je me demande comment ce chiffre est calculé. J'ai lu un certain nombre de ressources, dont celle de StackOverflow. question mais aucun ne généralise clairement le calcul.

Si possible, le calcul des paramètres apprenables par couche peut-il être généralisé ?

Par exemple, couche convolutive : nombre de filtres x largeur du filtre x hauteur du filtre.

175voto

hbaderts Points 11434

Voyons d'abord comment le nombre de paramètres apprenables est calculé pour chaque type individuel de couche que vous avez, puis calculons le nombre de paramètres dans votre exemple.

  • Couche d'entrée : Tout ce que fait la couche d'entrée est de lire l'image d'entrée, il n'y a donc aucun paramètre que vous pourriez apprendre ici.

  • Couches convolutives : Considérons une couche convolutive qui prend l des cartes de caractéristiques à l'entrée, et a k cartes de caractéristiques en sortie. La taille du filtre est n x m . Par exemple, cela ressemblera à ceci :

    Visualization of a convolutional layer

    Ici, l'entrée a l=32 cartes de caractéristiques en entrée, k=64 des cartes de caractéristiques en sortie, et la taille du filtre est de n=3 x m=3 . Il est important de comprendre que nous n'avons pas simplement un filtre 3x3, mais en fait un filtre 3x3x32, car notre entrée a 32 dimensions. Et nous apprenons 64 filtres 3x3x32 différents. Ainsi, le nombre total de poids est n*m*k*l . Ensuite, il y a également un terme de biais pour chaque carte de caractéristiques, de sorte que nous avons un nombre total de paramètres de (n*m*l+1)*k .

  • Couches de mise en commun : Les couches de mise en commun font par exemple ce qui suit : "remplacer un voisinage 2x2 par sa valeur maximale". Il n'y a donc aucun paramètre que vous pourriez apprendre dans une couche de mise en commun.

  • Couches entièrement connectées : Dans une couche entièrement connectée, toutes les unités d'entrée ont un poids distinct pour chaque unité de sortie. Pour n les entrées et m sorties, le nombre de poids est n*m . De plus, vous avez un biais pour chaque nœud de sortie, donc vous êtes à (n+1)*m paramètres.

  • Couche de sortie : La couche de sortie est une couche normale entièrement connectée, donc (n+1)*mn est le nombre d'entrées et m est le nombre de sorties.

La dernière difficulté concerne la première couche entièrement connectée : nous ne connaissons pas la dimensionnalité de l'entrée de cette couche, car il s'agit d'une couche convolutive. Pour la calculer, il faut partir de la taille de l'image d'entrée, et calculer la taille de chaque couche convolutive. Dans votre cas, Lasagne calcule déjà cela pour vous et rapporte les tailles - ce qui nous facilite la tâche. Si vous devez calculer vous-même la taille de chaque couche, c'est un peu plus compliqué :

  • Dans le cas le plus simple (comme votre exemple), la taille de la sortie d'une couche convolutive est de input_size - (filter_size - 1) dans votre cas : 28 - 4 = 24. Cela est dû à la nature de la convolution : nous utilisons par exemple un voisinage 5x5 pour calculer un point - mais les deux lignes et colonnes les plus extérieures n'ont pas de voisinage 5x5, donc nous ne pouvons pas calculer de sortie pour ces points. C'est pourquoi notre sortie est 2*2=4 lignes/colonnes plus petite que l'entrée.
  • Si l'on ne veut pas que la sortie soit plus petite que l'entrée, on peut mettre l'image à zéro (avec l'attribut pad paramètre de la couche convolutive dans Lasagne). Par exemple, si vous ajoutez 2 rangées/cols de zéros autour de l'image, la taille de la sortie sera de (28+4)-4=28. Donc, en cas de remplissage, la taille de sortie est de input_size + 2*padding - (filter_size -1) .
  • Si vous voulez explicitement sous-échantillonner votre image pendant la convolution, vous pouvez définir un stride, par ex. stride=2 ce qui signifie que vous déplacez le filtre par pas de 2 pixels. L'expression devient alors ((input_size + 2*padding - filter_size)/stride) +1 .

Dans votre cas, les calculs complets sont :

  #  name                           size                 parameters
---  --------  -------------------------    ------------------------
  0  input                       1x28x28                           0
  1  conv2d1   (28-(5-1))=24 -> 32x24x24    (5*5*1+1)*32   =     832
  2  maxpool1                   32x12x12                           0
  3  conv2d2   (12-(3-1))=10 -> 32x10x10    (3*3*32+1)*32  =   9'248
  4  maxpool2                     32x5x5                           0
  5  dense                           256    (32*5*5+1)*256 = 205'056
  6  output                           10    (256+1)*10     =   2'570

Ainsi, dans votre réseau, vous avez un total de 832 + 9'248 + 205'056 + 2'570 = 217'706 paramètres apprenables, ce qui est exactement ce que Lasagne rapporte.

0 votes

Excellente réponse, merci. La seule chose que je ne comprends toujours pas est comment la taille des couches convolutionnelles est calculée. Je ne sais pas d'où viennent les chiffres 24x24 et 10x10.

0 votes

J'ai ajouté plus de détails sur le calcul de la taille dans les couches convolutives - faites-moi savoir si cela vous aide.

0 votes

Bonjour @hbaderts , j'ai une autre question. Sur la base de ce tableau que vous avez ici, la taille du modèle se réfère à la somme de toutes les tailles individuelles, correct ? Pour un CNN, est-il raisonnable de comprendre que la taille du modèle est inversement proportionnelle au nombre de paramètres apprenables ? Pourriez-vous jeter un coup d'œil à stackoverflow.com/questions/43443342/ ?

14voto

Sandipan Dey Points 13663

En plus de l'excellente réponse de @hbaderts, je viens de trouver une formule pour un réseau I-C-P-C-P-H-O (puisque je travaillais sur un problème similaire), je la partage dans la figure ci-dessous, cela peut être utile.

enter image description here

De même, (1) la couche de convolution avec 2x2 stride et (2) la couche de convolution 1x1 stride + (max/avg) pooling avec 2x2 stride, contribuent chacune au même nombre de paramètres avec le "même" padding, comme on peut le voir ci-dessous :

enter image description here

-2voto

Gaurav Points 11

La taille des couches convolutionnelles est calculated=((n+2p-k)/s)+1

Ici,

  • n est l'entrée p est le remplissage k est le noyau ou le filtre s est la foulée

dans le cas ci-dessus

  • n=28 p=0 k=5 s=1

3 votes

Bonjour @gaurav dans la question il s'agit de paramètres apprenables et non de la taille de la sortie Vous avez répondu pour la taille de la sortie Clairement le mentionner sinon vous allez commencer à obtenir des votes négatifs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X