Introduction

La convolution est une opération mathématique qui rend le produit intégral de 2 fonctions (signaux), avec un des signaux à l’envers. Par exemple, ci-dessous, nous faisons la convolution de 2 signaux f(t) et g(t).

La première chose à faire est donc de retourner le signal g horizontalement (180 degrés), puis de faire glisser le g à l’envers sur f, en multipliant et en accumulant toutes ses valeurs.

L’ordre dans lequel les signaux sont convolués n’a pas d’importance pour le résultat final, donc conv(a,b)==conv(b,a)

Dans ce cas, considérez que le signal bleu f(τ) est notre signal d’entrée et g(t) notre noyau, le terme noyau est utilisé lorsque l’on utilise des convolutions pour filtrer les signaux.

Taille du signal de sortie 1D

Dans le cas de la convolution 1D, la taille de la sortie est calculée de cette manière :

outputSize=(InputSize-KernelSize)+1

Application des convolutions

Les gens utilisent la convolution sur le traitement des signaux pour les cas d’utilisation suivants :

Filtrage de signaux (audio 1D, traitement d’images 2D)

Vérifier la relation entre un signal et un autre

Trouver des modèles dans les signaux

Un exemple simple en matlab et python (engourdi)

Voici deux signaux x = (0,1,2,3,4) avec w = (1,-1,2).


Faire à la main

Pour mieux comprendre le concept de convolution, prenons l’exemple ci-dessus à la main. En gros, nous allons convoluer 2 signaux (x,w). La première chose est de retourner W horizontalement (O tourne à gauche de 180 degrés)

Ensuite, nous devons faire glisser le W retourné sur l’entrée X

Notez qu’aux étapes 3,4,5, la fenêtre inversée est complètement à l’intérieur du signal d’entrée. Ces résultats sont appelés des convolutions “valides”. Dans les cas où la fenêtre inversée n’est pas complètement à l’intérieur de la fenêtre d’entrée (X), nous pouvons les considérer comme nulles, ou nous pouvons calculer ce qui peut être calculé, par exemple à l’étape 1, nous multiplions 1 par zéro, et le reste est simplement ignoré.

Rembourrage d’entrée

Pour que la taille du résultat de la convolution soit égale à celle de l’entrée, et pour éviter un effet appelé convolution circulaire, nous ajoutons des zéros au signal.

L’endroit où vous placez les zéros dépend de ce que vous voulez faire, c’est-à-dire : sur le cas 1D, vous pouvez les concaténer à chaque extrémité, mais sur un cas 2D, vous les placez normalement tout autour du signal original.

Sur matlab, vous pouvez utiliser la commande “padarray” pour compléter la saisie :

>> x

x( :,:,1) =

1 1 0 2 0

2 2 2 2 1

0 0 0 2 1

2 2 2 2 1

2 0 2 2 1

x( :,:,2) =

2 1 0 0 0

0 2 0 1 0

1 0 1 2 0

1 2 0 2 1

1 2 1 2 2

x( :,:,3) =

2 1 1 2 2

1 1 1 0 0

2 0 1 0 2

0 2 0 2 1

0 0 2 1 0

>> padarray(x, [1 1])

ans( :,:,1) =

0 0 0 0 0 0 0

0 1 1 0 2 0 0

0 2 2 2 2 1 0

0 0 0 0 2 1 0

0 2 2 2 2 1 0

0 2 0 2 2 1 0

0 0 0 0 0 0 0

ans( :,:,2) =

0 0 0 0 0 0 0

0 2 1 0 0 0 0

0 0 2 0 1 0 0

0 1 0 1 2 0 0

0 1 2 0 2 1 0

0 1 2 1 2 2 0

0 0 0 0 0 0 0

ans( :,:,3) =

0 0 0 0 0 0 0

0 2 1 1 2 2 0

0 1 1 1 0 0 0

0 2 0 1 0 2 0

0 0 2 0 2 1 0

0 0 0 2 1 0 0

0 0 0 0 0 0 0

Taille de sortie pour le 2D

Veuillez connaître la taille de notre sortie après avoir effectué quelques opérations de convolution sur celle-ci. Heureusement, il existe une formule pratique qui nous dit exactement cela.

Si nous considérons la convolution d’une entrée, de dimensions spatiales [H, W] avec P, avec un noyau carré de taille F et en utilisant la foulée S, alors la taille de la sortie de la convolution est définie comme suit :

outputSizeW=(W-F+2P)/S+1 outputSizeH=(H-F+2P)/S+1 output

F est la taille du noyau, nous utilisons normalement des noyaux carrés, donc F est à la fois la largeur et la hauteur du noyau

Mise en œuvre de l’opération Convolution

L’exemple ci-dessous concerne une entrée 5x5x3 (LxHx3), avec un niveau de conv avec les paramètres suivants : Stride=2, Pad=1, F=3 (noyau 3×3), et K=2 (deux filtres).

Notre entrée a 3 canaux, nous avons donc besoin d’un poids de noyau 3x3x3. Nous avons 2 filtres (K=2), donc nous aurons 2 activations de sortie à la fin. En outre, nous pouvons calculer la taille de ces deux sorties : (5 – 3 + 2)/2 + 1 = 3.

Ce code ci-dessous (version vanille) ne peut pas être utilisé dans la vie réelle car il sera lent mais il est bon pour une compréhension de base. Habituellement, les bibliothèques d’apprentissage profond font la convolution comme une multiplication matricielle unique, en utilisant la méthode im2col/col2im.

%% Convolution n dimensions

% Le code suivant n’est qu’une extension de conv2d_vanila pour n dimensions.

Paramètres en % :

Entrée % : H x L x profondeur

% K : noyau F x F x profondeur

% S : foulée (nombre de pixels que la fenêtre glissera sur l’entrée)

Cette mise en œuvre est comme le paramètre “valide” sur la convolution normale

fonction outConv = convn_vanilla(input, kernel, S)

Obtenez la taille de l’entrée en termes de lignes et de colonnes. Les poids doivent avoir

% même profondeur que le volume d’entrée (image)

[rowsIn, colsIn, ~] = taille(input) ;

% Obtenir le volume dimensio

depthInput = ndims(input) ;

% Obtenir la taille du noyau, en considérant toujours un noyau carré

F = taille (noyau,1) ;

%% Initialisation des résultats

sizeRowsOut = ((rowsIn-F)/S) + 1 ;

sizeColsOut = ((colsIn-F)/S) + 1 ;

outConvAcc = zéros (sizeRowsOut , sizeColsOut, depthInput) ;

%% Effectuer la convolution

% Convolution de chaque canal sur l’entrée avec son canal de noyau respectif,

% à la fin additionnent tous les résultats des chaînes.

pour profondeur=1:profondeurEntrée

% Sélection de l’entrée et du canal de courant du noyau

inputCurrDepth = input( :,:,profondeur) ;

kernelCurrDepth = kernel( :,:,depth) ;

% Itération sur chaque ligne et chaque col, (en utilisant la foulée)

pour r=1:S :(rowsIn-1)

pour c=1:S :(colsIn-1)

% Évitez de prélever des échantillons de l’image.

if (((c+F)-1) <= colsIn) && (((r+F)-1) <= rowsIn)

% Sélectionner la fenêtre sur le volume d’entrée (patch)

sampleWindow = inputCurrDepth(r :(r+F)-1,c :(c+F)-1) ;

% Faire le produit du point

dotProd = sum(sampleWindow( 🙂 .* kernelCurrDepth( :)) ;

% Stockage du résultat

outConvAcc(ceil(r/S),ceil(c/S),depth) = dotProd ;

fin

fin

fin

fin

% Somme des éléments sur la dimension du volume d’entrée (somme de tous les canaux)

outConv = somme(outConvAcc,depthInput) ;

fin