Qu’est-ce qu’une convolution ?
Une convolution fait glisser un petit filtre sur une grille de nombres pour y repérer un motif, comme un bord ou un changement brusque. C’est l’idée des réseaux de neurones convolutifs (CNN, de l’anglais convolutional neural network), utilisés pour lire des images.
Une photo de 1 000 par 1 000 points compte un million de nombres. Un filtre de neuf poids suffit pourtant à y chercher un bord.
À la fin de cette leçon
Remarque
Je peux expliquer comment une convolution repère un motif dans une grille de nombres.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Convolution | faire glisser un filtre sur des nombres et calculer à chaque position | |
| Filtre | une petite liste de poids qui cherche un motif | [-1, 0, 1] |
| Carte de sortie | les résultats du filtre, un par position | |
| Agrégation par le maximum | garder le plus grand nombre de chaque petit groupe | |
| Réseau convolutif | un réseau dont les premières couches sont des filtres |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un filtre glisse et repère un motif
Prenez huit jours de locations, en centaines : 2, 2, 3, 6, 6, 5, 2, 2. Prenez un filtre de trois poids : -1, 0 et 1.
On pose le filtre sur les trois premiers jours. On multiplie chaque valeur par son poids, puis on additionne. On décale d’un jour et on recommence. Un grand résultat positif signale une hausse.
Exemple travaillé : le filtre qui glisse
| Position | Trois valeurs | Calcul | Résultat |
|---|---|---|---|
| 1 | 2, 2, 3 | -2 + 0 + 3 | 1 |
| 2 | 2, 3, 6 | -2 + 0 + 6 | 4 |
| 3 | 3, 6, 6 | -3 + 0 + 6 | 3 |
| 4 | 6, 6, 5 | -6 + 0 + 5 | -1 |
| 5 | 6, 5, 2 | -6 + 0 + 2 | -4 |
| 6 | 5, 2, 2 | -5 + 0 + 2 | -3 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Le filtre sur les huit jours
docker exec jupyter python3 -c "s = [2, 2, 3, 6, 6, 5, 2, 2]; print([-s[n] + s[n + 2] for n in range(6)])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Calculer une position en Python
# Huit jours de locations, en centaines.
signal = [2, 2, 3, 6, 6, 5, 2, 2]
filtre = [-1, 0, 1]
position = 0
total = 0
for k in range(len(filtre)):
total = total + signal[position + k] * filtre[k]
print("position", position, ":", total)
# Passez position à 2, puis à 4.
# Le résultat monte-t-il ou descend-il avec le signal ?
Le filtre glisse aussi sur une image
Une image est une grille de nombres : 0 pour un point sombre, 1 pour un point clair. Le filtre est lui aussi une petite grille, ici de deux sur deux.
Il se pose sur un carré de la grille. On multiplie case par case, on additionne les quatre produits, et on décale. La carte de sortie a n - f + 1 colonnes pour une image de n et un filtre de f.
Exemple travaillé : l’image et le filtre
| Ligne | Image : 4 colonnes | Filtre : 2 colonnes |
|---|---|---|
| 1 | 0, 0, 1, 1 | -1, 1 |
| 2 | 0, 0, 1, 1 | -1, 1 |
| 3 | 0, 0, 1, 1 | |
| 4 | 0, 0, 1, 1 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Exemple travaillé : la carte de sortie
| Position du filtre | Quatre valeurs | Calcul | Résultat |
|---|---|---|---|
| Colonnes 1 et 2 | 0, 0, 0, 0 | 0 × -1 + 0 × 1 + 0 × -1 + 0 × 1 | 0 |
| Colonnes 2 et 3 | 0, 1, 0, 1 | 0 × -1 + 1 × 1 + 0 × -1 + 1 × 1 | 2 |
| Colonnes 3 et 4 | 1, 1, 1, 1 | 1 × -1 + 1 × 1 + 1 × -1 + 1 × 1 | 0 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un filtre partage ses poids sur toute l’image
Une couche dense relierait chaque point de l’image à chaque neurone. Pour une image de 28 sur 28 points, un seul neurone aurait 784 poids.
Un filtre de 3 sur 3 garde ses 9 poids et les réutilise partout. Le réseau a donc moins de poids à régler, et il trouve le même motif où qu’il soit.
Exemple travaillé : compter les poids
| Couche | Poids par neurone ou filtre | Remarque |
|---|---|---|
| Dense, image de 28 × 28 | 784 | Un jeu de poids par neurone |
| Filtre de 3 × 3 | 9 | Le même jeu partout |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
Beaucoup pensent qu’on choisit les filtres à la main. Dans un réseau convolutif, les poids des filtres sont appris par descente de gradient, comme les autres. Le filtre -1, 0, 1 n’est qu’un exemple de ce qu’un filtre peut devenir.
L’agrégation par le maximum réduit la carte
Après le filtre, la carte est encore grande. L’agrégation par le maximum (max pooling en anglais) la réduit. On coupe la carte en petits groupes et on garde le plus grand nombre de chacun.
Avec des groupes de deux, la liste 1, 4, 3, -1, -4, -3 donne 4, 3 et -3. On perd la place exacte, mais on garde le signe que le motif est là.
Les maxima par groupes de deux
docker exec jupyter python3 -c "c = [1, 4, 3, -1, -4, -3]; print([max(c[n], c[n + 1]) for n in range(0, 6, 2)])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Dans votre carnet : le filtre avec NumPy
import numpy as np
signal = [2, 2, 3, 6, 6, 5, 2, 2]
filtre = [-1, 0, 1]
# correlate glisse le filtre sans le retourner, comme un réseau convolutif.
print(np.correlate(signal, filtre, mode="valid"))
# Remplacez le filtre par [1, 1, 1] : que mesure maintenant la liste ?