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.
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.
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:
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
.
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
.(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é:
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.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)
.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.
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.
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: