web-dev-qa-db-fra.com

Comment calculer le nombre de paramètres pour le réseau neuronal convolutionnel?

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

L’architecture CNN que j’ai pour le moment, et qui n’inclut aucune couche de suppression, 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 génère les informations de couche suivantes:

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

et affiche le nombre de paramètres pouvant être appris sous la forme 217 ​​706

Je me demande comment ce nombre est calculé? J'ai lu un certain nombre de ressources, y compris celle de question de StackOverflow, mais aucune 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.

34
Waddas

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

  • Couche d'entrée : Tout ce que la couche d'entrée fait est de lire l'image d'entrée. Par conséquent, aucun paramètre ne peut être appris ici.
  • Couches convolutives : considérons une couche convolutive qui prend l les cartes de caractéristiques en entrée et a k les cartes de caractéristiques sortie. La taille du filtre est n x m. Par exemple, cela ressemblera à ceci:

    Visualization of a convolutional layer

    Ici, l'entrée a des cartes de caractéristiques l=32 En entrée, des cartes de fonction k=64 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 réalité 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 de n*m*k*l. Ensuite, il y a aussi un terme de biais pour chaque carte de caractéristiques, nous avons donc un nombre total de paramètres de (n*m*l+1)*k.

  • Couches de regroupement : les couches de regroupement, par exemple. procédez comme suit: "remplacer un quartier 2x2 par sa valeur maximale". Il n'y a donc aucun paramètre que vous pourriez apprendre dans une couche de regroupement.
  • 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 entrées et m sorties, le nombre de poids est de n*m. De plus, vous avez un biais pour chaque nœud de sortie, vous êtes donc à des paramètres (n+1)*m.
  • Couche de sortie : la couche de sortie est une couche entièrement connectée normale, donc paramètres (n+1)*m, Où n est le nombre d'entrées et m est le nombre de sorties.

La dernière difficulté est 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 le calculer, nous devons commencer par la taille de l'image d'entrée et calculer la taille de chaque couche convolutive. Dans votre cas, Lasagne calcule déjà cela et en indique 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 dans votre exemple), la taille de la sortie d'une couche de convolution est 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 externes n’ont pas de voisinage 5x5; nous ne pouvons donc calculer aucune sortie pour ces points. C'est pourquoi notre sortie est 2 * 2 = 4 lignes/colonnes plus petites que l'entrée.
  • Si l’on ne veut pas que la sortie soit plus petite que l’entrée, on peut appliquer un zéro-image à l’image (avec le paramètre pad de la couche de convolution de Lasagne). Par exemple. si vous ajoutez 2 lignes/colonnes de zéros autour de l'image, la taille de sortie sera (28 + 4) -4 = 28. Donc, en cas de remplissage, la taille de sortie est input_size + 2*padding - (filter_size -1).
  • Si vous souhaitez explicitement sous-échantillonner votre image lors de la convolution, vous pouvez définir une foulée, par exemple. stride=2, Ce qui signifie que vous déplacez le filtre par pas de 2 pixels. Ensuite, l'expression devient ((input_size + 2*padding - filter_size)/stride) +1.

Dans votre cas, les calculs complets sont les suivants:

  #  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

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

81
hbaderts

s'appuyant sur 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), le partager dans la figure ci-dessous peut être utile.

enter image description here

En outre, (1) couche de convolution avec foulée 2x2 et (2) couche de convolution 1x1 foulée + pool (max/moy) avec 2x2 foulées, chacune contribue le même nombre de paramètres avec le même remplissage, comme on peut le voir ci-dessous:

enter image description here

7
Sandipan Dey