Dans un réseau neuronal convolutif (CNN), lors de la convolution de l'image, l'opération est-elle utilisée le produit scalaire ou la somme de la multiplication par élément?


12

L'exemple ci-dessous est tiré des conférences de deeplearning.ai montre que le résultat est la somme du produit élément par élément (ou "multiplication par élément". Les nombres rouges représentent les poids dans le filtre:

(11)+(10)+(11)+(00)+(11)+(10)+(01)+(00)+(11)=1+0+1+0+1+0+0+0+1=4

entrez la description de l'image ici

TOUTEFOIS, la plupart des ressources disent que c'est le produit scalaire qui est utilisé:

"… Nous pouvons ré-exprimer la sortie du neurone comme, où est le terme de biais. En d'autres termes, nous pouvons calculer la sortie par y = f (x * w) où b est le terme de biais. En d'autres termes, nous peut calculer la sortie en effectuant le produit scalaire des vecteurs d'entrée et de poids, en ajoutant le terme de biais pour produire le logit, puis en appliquant la fonction de transformation. "

Buduma, Nikhil; Locascio, Nicholas. Fondements du Deep Learning: conception d'algorithmes d'intelligence artificielle de nouvelle génération (p. 8). O'Reilly Media. Édition Kindle.

"Nous prenons le filtre 5 * 5 * 3 et le faisons glisser sur l'image complète et en cours de route, prenons le produit scalaire entre le filtre et les morceaux de l'image d'entrée. Pour chaque produit scalaire pris, le résultat est un scalaire."

https://medium.com/technologymadeeasy/the-best-explanation-of-convolutional-neural-networks-on-the-internet-fbb8b1ad5df8

"Chaque neurone reçoit des entrées, effectue un produit scalaire et le suit éventuellement avec une non-linéarité."

http://cs231n.github.io/convolutional-networks/

"Le résultat d'une convolution équivaut désormais à effectuer une grande matrice multipliée np.dot (W_row, X_col), qui évalue le produit scalaire entre chaque filtre et chaque emplacement de champ récepteur."

http://cs231n.github.io/convolutional-networks/

Cependant, lorsque je recherche comment calculer le produit scalaire des matrices , il semble que le produit scalaire ne soit pas la même chose que la somme de la multiplication élément par élément. Quelle opération est réellement utilisée (multiplication élément par élément ou produit scalaire?) Et quelle est la principale différence?


1
Le produit scalaire n'est pas précis. Je dirais que c'est la somme de la Hadamard productzone sélectionnée et du noyau de convolution.
JP Zhang

c'est un produit scalaire mais au lieu d'utiliser la totalité de la matrice, les patchs sont déplacés, donc nous ne pourrions pas utiliser la fonction du produit scalaire car nous aurions à passer en boucle en passant par différentes matrices en déplaçant le patch / la fenêtre autour de toute l'image / la matrice
Mr-Programs

Réponses:


13

Toute couche donnée dans un CNN a généralement 3 dimensions (nous les appellerons hauteur, largeur, profondeur). La convolution produira une nouvelle couche avec une nouvelle (ou la même) hauteur, largeur et profondeur. L'opération est cependant effectuée différemment sur la hauteur / largeur et différemment sur la profondeur et c'est ce qui, je pense, est source de confusion.

Voyons d'abord comment l'opération de convolution sur la hauteur et la largeur de la matrice d'entrée. Ce cas est effectué exactement comme illustré dans votre image et est très certainement une multiplication par élément des deux matrices .

En théorie :
les convolutions bidimensionnelles (discrètes) sont calculées par la formule ci-dessous:

C[m,n]=uυUNE[m+u,n+υ]B[u,υ]

Comme vous pouvez voir chaque élément de C est calculé comme la somme des produits d'un seul élément de UNE avec un seul élément de B. Cela signifie que chaque élément deC est calculé à partir de la somme de la multiplication par élément de UNE et B.

En pratique :
vous pouvez tester l'exemple ci-dessus avec n'importe quel nombre de packages (je vais utiliser scipy ):

import numpy as np
from scipy.signal import convolve2d

A = np.array([[1,1,1,0,0],[0,1,1,1,0],[0,0,1,1,1],[0,0,1,1,0],[0,1,1,0,0]])
B = np.array([[1,0,1],[0,1,0],[1,0,1]])
C = convolve2d(A, B, 'valid')
print(C)

Le code ci-dessus produira:

[[4 3 4]
 [2 4 3]
 [2 3 4]]

Maintenant, l'opération de convolution sur la profondeur de l'entrée peut en fait être considérée comme un produit scalaire car chaque élément de la même hauteur / largeur est multiplié avec le même poids et ils sont additionnés ensemble. Cela est plus évident dans le cas des convolutions 1x1 (généralement utilisées pour manipuler la profondeur d'une couche sans modifier ses dimensions). Cependant, cela ne fait pas partie d'une convolution 2D (d'un point de vue mathématique), mais quelque chose que les couches convolutionnelles font dans les CNN.

Notes :
1: Cela étant dit, je pense que la plupart des sources que vous avez fournies ont des explications trompeuses pour le moins et ne sont pas correctes. Je ne savais pas que de nombreuses sources ont cette opération (qui est l'opération la plus essentielle dans les CNN) mal. Je suppose que cela a quelque chose à voir avec le fait que les convolutions additionnent le produit entre les scalaires et le produit entre deux scalaires est également appelé un produit scalaire .
2: Je pense que la première référence se réfère à une couche entièrement connectée au lieu d'une couche convolutionnelle. Si tel est le cas, une couche FC exécute le produit scalaire comme indiqué. Je n'ai pas le reste du contexte pour le confirmer.

tl; dr L'image que vous avez fournie est 100% correcte sur la façon dont l'opération est effectuée, mais ce n'est pas l'image complète. Les couches CNN ont 3 dimensions, dont deux sont traitées comme illustré. Ma suggestion serait de vérifier comment les couches convolutives gèrent la profondeur de l'entrée (le cas le plus simple que vous puissiez voir est des convolutions 1x1).


Merci pour la réponse. Selon votre suggestion concernant la recherche de la façon dont les couches convolutionnelles gèrent la profondeur de l'entrée, consultez la section Démonstration de convolution sur ce lien: cs231n.github.io/convolutional-networks . J'ai calculé les nombres dans une feuille de calcul et il semble que le nombre final qui va dans le volume de sortie est juste la somme de la multiplication par élément de chaque filtre et champ récepteur (qui somme à un nombre par volume de couleur), puis le trois chiffres viennent d'être additionnés avec le biais ...
Ryan Chase

5
Oui, ce que je voulais souligner, c'est que cela équivaut à un produit scalaire entre le vecteur de pixels le long de la troisième dimension (profondeur, les filtres l'appellent ce que vous voulez) et le poids scalaire du noyau de convolution.
Djib2011

3

L'opération est appelée convolution qui implique une somme de multiplication élément par élément, qui à son tour est la même chose qu'un produit scalaire sur des matrices multidimensionnelles que les gens ML appellent des tenseurs. Si vous l'écrivez en boucle, il ressemblera à ce code pseudo Python:

for i in 0:3:
  for j in 0:3:
    s = 0
    for k in 0:3:
      for l in 0:3:
        s += A[i+k,j+l]*C[k,l]
    Z[i,j] = s

Ici, A est votre matrice d'entrée 5x5, C est un filtre 3x3 et Z est une matrice de sortie 3x3.

La différence subtile avec un produit scalaire est que généralement un produit scalaire se trouve sur l'ensemble des vecteurs, tandis qu'en convolution, vous produisez le produit scalaire sur le sous-ensemble mobile (fenêtre) de la matrice d'entrée, vous pouvez l'écrire comme suit pour remplacer les deux plus imbriqués boucles dans le code ci-dessus:

Z[i,j] = dot(A[i:i+2,j:j+2],C)

1

Je crois que la clé est que lorsque le filtre est en train de convoluer une partie de l'image (le "champ récepteur") chaque numéro dans le filtre (c'est-à-dire chaque poids) est d' abord aplati en format vectoriel . De même, les pixels de l'image sont également aplatis au format vectoriel . ALORS, le produit scalaire est calculé. Ce qui revient exactement à trouver la somme de la multiplication élément par élément (élément par élément).

Bien sûr, ces vecteurs aplatis peuvent également être combinés dans un format matriciel, comme le montre l'image ci-dessous. Dans ce cas, une véritable multiplication matricielle peut être utilisée, mais il est important de noter que l'aplatissement des pixels de l'image de chaque convolution ainsi que le filtre de pondération est le précurseur.

entrez la description de l'image ici

crédit d'image: TensorFlow et Deep Learning sans doctorat, partie 1 (Google Cloud Next '17)


0

Les interprétations des éléments et des produits scalaires sont correctes. Lorsque vous convoluez deux tenseurs, X de forme (h, w, d) et Y de forme (h, w, d), vous faites une multiplication par élément. C'est cependant la même chose que le produit scalaire de la transposition X et Y. Vous pouvez développer l'équation mathématique, les formes et les indices correspondent.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.