Autoencodeurs : Guide complet — Principes, Exemples et Implémentation Python
Résumé
Les autoencodeurs sont des réseaux de neurones artificiels conçus pour apprendre des représentations compactes de données de manière non supervisée. Leur objectif principal est la réduction de dimensionalité non linéaire : ils compriment les données d’entrée dans un espace de plus faible dimension (le « goulot » ou bottleneck), puis tentent de reconstruire les données originales à partir de cette représentation compressée. Contrairement à l’Analyse en Composantes Principales (ACP), les autoencodeurs capturent des relations non linéaires complexes, ce qui les rend extrêmement puissants pour les données structurées comme les images, le son ou le texte.
Principe mathématique
Un autoencodeur se compose de deux sous-réseaux principaux :
1. L’encodeur
L’encodeur $E$ transforme l’entrée $x$ en une représentation latente $h$ de dimension réduite :
$$h = \sigma(W_e x + b_e)$$
où :
– $x \in \mathbb{R}^n$ est le vecteur d’entrée de dimension $n$,
– $W_e \in \mathbb{R}^{d \times n}$ est la matrice de poids de l’encodeur (avec $d < n$),
– $b_e \in \mathbb{R}^d$ est le vecteur de biais,
– $\sigma$ est une fonction d’activation non linéaire (ReLU, sigmoïde, etc.),
– $h \in \mathbb{R}^d$ est la représentation latente (le goulot), de dimension $d$ strictement inférieure à $n$.
2. Le goulot (bottleneck)
Le goulot est la couche de plus petite dimension du réseau. C’est là que réside toute l’essence de la réduction de dimensionalité : le réseau est forcé de sélectionner les informations les plus pertinentes et de les encoder dans un espace restreint. La dimension $d$ du goulot est un hyperparamètre critique : trop grand, le réseau n’apprend qu’à copier ; trop petit, il perd des informations essentielles.
3. Le décodeur
Le décodeur $D$ tente de reconstruire l’entrée originale à partir de la représentation latente :
$$x’ = \sigma(W_d h + b_d)$$
où :
– $W_d \in \mathbb{R}^{n \times d}$ est la matrice de poids du décodeur,
– $b_d \in \mathbb{R}^n$ est le vecteur de biais du décodeur,
– $x’ \in \mathbb{R}^n$ est la reconstruction de l’entrée originale.
4. Fonction de perte : minimisation de la reconstruction
L’autoencodeur est entraîné en minimisant l’erreur de reconstruction entre l’entrée originale et sa reconstruction :
$$\mathcal{L}(x, x’) = ||x – x’||^2 = \sum_{i=1}^{n} (x_i – x’_i)^2$$
Cette fonction de coût (erreur quadratique moyenne, MSE) pénalise chaque écart entre la valeur reconstruite et la valeur originale. Le réseau apprend ainsi à préserver les informations les plus importantes à travers le goulot. L’optimisation se fait par descente de gradient (ou des variantes comme Adam), rétropropageant le gradient de la perte à travers les deux sous-réseaux.
Intuition : le fichier zip intelligent
Imaginez que vous vouliez compresser un fichier zip. Un algorithme de compression classique réduit la taille du fichier en encodant l’information de manière plus efficace. Un autoencodeur fonctionne de manière similaire, mais intelligente :
- L’encodeur compresse : il analyse les données et les transforme en une représentation compacte dans le goulot, en conservant uniquement l’information essentielle pour reconstruire l’original.
- Le décodeur décompresse : il prend cette représentation compacte et tente de reconstituer les données originales aussi fidèlement que possible.
Si l’autoencodeur fonctionne bien, le goulot contient une représentation fidèle mais compacte des données. C’est comme si le réseau avait découvert les « caractéristiques fondamentales » des données : pour des visages, ce pourrait être la forme du visage, la position des yeux, la couleur de peau ; pour des textes, le thème général ; pour des signaux, les fréquences dominantes.
La différence cruciale avec un zip classique est que l’autoencodeur apprend la compression à partir des données elles-mêmes, sans règle préétablie. Il s’adapte à la structure spécifique du jeu de données.
Implémentation Python
Exemple 1 : Autoencodeur simple sur MNIST avec Keras/TensorFlow
Commençons par un autoencodeur de base entraîné sur les chiffres manuscrits MNIST. Les images 28×28 (=784 pixels) seront compressées dans un espace de 32 dimensions.
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.datasets import mnist
# Chargement des données
(x_train, _), (x_test, _) = mnist.load_data()
# Normalisation et aplatissement
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
x_train = x_train.reshape(-1, 784)
x_test = x_test.reshape(-1, 784)
# Dimension du goulot
encoding_dim = 32
# Architecture de l'autoencodeur
input_img = Input(shape=(784,))
# Encodeur : 784 -> 128 -> 32
encodeur = Dense(128, activation='relu')(input_img)
encodeur = Dense(encoding_dim, activation='relu', name='bottleneck')(encodeur)
# Décodeur : 32 -> 128 -> 784
decodeur = Dense(128, activation='relu')(encodeur)
decodeur = Dense(784, activation='sigmoid', name='output')(encodeur)
# Modèle complet
autoencodeur = Model(inputs=input_img, outputs=decodeur)
autoencodeur.compile(optimizer='adam', loss='mse')
# Entraînement
autoencodeur.fit(x_train, x_train,
epochs=50,
batch_size=256,
shuffle=True,
validation_split=0.1,
verbose=1)
# Visualisation des résultats
encodeur_modele = Model(inputs=input_img, outputs=encodeur)
reconstructions = autoencodeur.predict(x_test[:10])
fig, axes = plt.subplots(2, 10, figsize=(20, 4))
for i in range(10):
axes[0, i].imshow(x_test[i].reshape(28, 28), cmap='gray')
axes[0, i].axis('off')
axes[1, i].imshow(reconstructions[i].reshape(28, 28), cmap='gray')
axes[1, i].axis('off')
axes[0, 0].set_ylabel('Original', fontsize=14)
axes[1, 0].set_ylabel('Reconstruit', fontsize=14)
plt.tight_layout()
plt.show()
Cet autoencodeur simple apprend à réduire les images de 784 dimensions à seulement 32, soit une compression d’un facteur 24,5, tout en préservant suffisamment d’information pour reconnaître les chiffres.
Exemple 2 : Comparaison avec l’ACP en 2D
Comparons la réduction de dimensionalité des autoencodeurs avec l’ACP (Analyse en Composantes Principales). L’ACP est une méthode linéaire, tandis que l’autoencodeur est non linéaire.
from sklearn.decomposition import PCA
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
# Chargement
(x_train, y_train), _ = mnist.load_data()
x_train = x_train.reshape(-1, 784).astype('float32') / 255.0
# --- ACP ---
pca = PCA(n_components=2)
x_pca = pca.fit_transform(x_train[:5000])
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
scatter = plt.scatter(x_pca[:, 0], x_pca[:, 1], c=y_train[:5000],
cmap='tab10', alpha=0.5, s=5)
plt.colorbar(scatter, ticks=range(10))
plt.title('ACP : réduction linéaire en 2D')
# --- Autoencodeur vers 2D ---
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
input_img = Input(shape=(784,))
encodeur = Dense(128, activation='relu')(input_img)
encodeur = Dense(64, activation='relu')(encodeur)
encodeur = Dense(2, activation='linear', name='latente_2d')(encodeur)
decodeur = Dense(64, activation='relu')(encodeur)
decodeur = Dense(128, activation='relu')(decodeur)
decodeur = Dense(784, activation='sigmoid')(decodeur)
ae = Model(inputs=input_img, outputs=decodeur)
ae.compile(optimizer='adam', loss='mse')
ae.fit(x_train, x_train, epochs=30, batch_size=256, verbose=1)
encodeur_2d = Model(inputs=input_img, outputs=encodeur)
x_ae = encodeur_2d.predict(x_train[:5000])
plt.subplot(1, 2, 2)
scatter = plt.scatter(x_ae[:, 0], x_ae[:, 1], c=y_train[:5000],
cmap='tab10', alpha=0.5, s=5)
plt.colorbar(scatter, ticks=range(10))
plt.title('Autoencodeur : réduction non linéaire en 2D')
plt.tight_layout()
plt.show()
On observe typiquement que l’autoencodeur sépare mieux les classes de chiffres que l’ACP, car il capture des frontières non linéaires entre les clusters. Les chiffres manuscrits se regroupent en amas distincts dans l’espace latent, tandis que l’ACP les superpose davantage.
Exemple 3 : Autoencodeur débruiteur (Denoising Autoencoder)
Un autoencodeur débruiteur reçoit en entrée des données corrompues par du bruit et doit reconstruire les données propres. Cela force le réseau à apprendre des représentations robustes et généralisables.
import numpy as np
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
# Chargement et normalisation
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
x_train = x_train.reshape(-1, 784)
x_test = x_test.reshape(-1, 784)
# Ajout de bruit gaussien
bruit = 0.5
x_train_bruite = x_train + bruit * np.random.normal(size=x_train.shape)
x_test_bruite = x_test + bruit * np.random.normal(size=x_test.shape)
# Clamp entre 0 et 1
x_train_bruite = np.clip(x_train_bruite, 0., 1.)
x_test_bruite = np.clip(x_test_bruite, 0., 1.)
# Architecture
input_img = Input(shape=(784,))
x = Dense(256, activation='relu')(input_img)
x = Dense(128, activation='relu')(x)
encoded = Dense(64, activation='relu', name='latent')(x)
x = Dense(128, activation='relu')(encoded)
x = Dense(256, activation='relu')(x)
decoded = Dense(784, activation='sigmoid')(x)
denoiser = Model(inputs=input_img, outputs=decoded)
denoiser.compile(optimizer='adam', loss='mse')
# Entraînement : entrée bruitée -> sortie propre
denoiser.fit(x_train_bruite, x_train,
epochs=50,
batch_size=256,
shuffle=True,
validation_split=0.1)
# Résultats
n = 8
idx = np.random.choice(len(x_test), n, replace=False)
bruitees = x_test_bruite[idx]
nettoyees = denoiser.predict(bruitees)
fig, axes = plt.subplots(3, n, figsize=(20, 6))
for i in range(n):
axes[0, i].imshow(x_test[idx[i]].reshape(28, 28), cmap='gray')
axes[0, i].set_title('Original')
axes[1, i].imshow(bruitees[i].reshape(28, 28), cmap='gray')
axes[1, i].set_title('Bruité')
axes[2, i].imshow(nettoyees[i].reshape(28, 28), cmap='gray')
axes[2, i].set_title('Nettoyé')
for j in range(3):
axes[j, i].axis('off')
plt.tight_layout()
plt.show()
L’autoencodeur débruiteur est particulièrement utile en traitement d’images, où il permet de supprimer le bruit tout en préservant les détails structurels importants.
Hyperparamètres clés
Le choix des hyperparamètres est crucial pour obtenir un autoencodeur efficace :
| Hyperparamètre | Rôle | Recommandation |
|---|---|---|
| Taille du goulot | Dimension de la représentation latente | 2-64 pour la visualisation, 32-256 pour les applications générales |
| Nombre de couches | Profondeur de l’encodeur et du décodeur | 2-4 couches pour des données tabulaires, plus pour les images |
| Fonction d’activation | Non-linéarité introduite | ReLU pour les couches cachées, sigmoïde en sortie pour les images normalisées |
| Regularization | Éviter le surapprentissage | Dropout (0.2-0.5), L1/L2 sur les poids, ou activation sparse |
| Learning rate | Vitesse d’apprentissage | 0.001 avec Adam est un bon point de départ |
| Batch size | Nombre d’échantillons par mise à jour | 128-256 pour MNIST, 32-64 pour les grandes images |
| Epochs | Nombre de passages complets sur les données | 20-100 selon la complexité ; utiliser l’arrêt anticipé (early stopping) |
Une règle empirique importante : la taille du goulot détermine le compromis entre fidélité de la reconstruction et compression. Si le goulot est trop grand, l’autoencodeur peut apprendre une simple identité (copier bêtement l’entrée en sortie). Pour éviter cela, on peut ajouter une régularisation sparse (pénaliser l’activation des neurones cachés) ou utiliser un autoencodeur débruiteur.
Avantages et limites
Avantages
- Réduction non linéaire : capture des relations complexes que l’ACP ne peut pas modéliser
- Apprentissage non supervisé : ne nécessite pas d’étiquettes ; les données brutes suffisent
- Flexibilité architecturale : on peut empiler autant de couches que nécessaire, utiliser des convolutions pour les images, ou des réseaux récurrents pour les séquences
- Polyvalence : au-delà de la réduction de dimensionalité, les autoencodeurs servent au débruitage, à la génération (VAE), à la détection d’anomalie
- Représentations riches : l’espace latent encode souvent des caractéristiques sémantiques utiles pour des tâches aval
Limites
- Coût computationnel : l’entraînement nécessite plus de ressources que des méthodes classiques comme l’ACP
- Interprétation difficile : contrairement aux composantes principales, les axes latents sont rarement interprétables directement
- Reproduction aléatoire : les poids initiaux sont aléatoires, ce qui rend les résultats légèrement variables d’une exécution à l’autre
- Risque de surapprentissage : un autoencodeur trop puissant peut apprendre l’identité au lieu de compresser
- Pas de garantie de structure : l’espace latent n’est pas toujours continu ni bien structuré (contrairement aux VAE)
4 cas d’usage concrets
Cas 1 — Détection d’anomalies industrielles
Dans une usine, on entraîne un autoencodeur sur les mesures de capteurs en fonctionnement normal. En production, une erreur de reconstruction élevée signale un comportement inhabituel : un roulement qui s’use, une température anormale, une vibration suspecte. L’avantage est que cette approche ne nécessite aucun exemple de panne pour l’entraînement.
Cas 2 — Compression et prétraitement d’images
Les autoencodeurs convolutifs peuvent réduire des images haute résolution à une représentation latente compacte utilisée comme entrée pour des réseaux plus petits (classification, segmentation). Cela réduit considérablement le temps d’entraînement et la mémoire nécessaire, tout en préservant l’information sémantique.
Cas 3 — Débruitage de signaux biomédicaux
En électrocardiographie (ECG) ou en électroencéphalographie (EEG), les signaux sont souvent contaminés par du bruit électrique, des artefacts de mouvement, ou des interférences 50 Hz. Un autoencodeur débruiteur entraîné sur des couples (signal bruité, signal propre) restaure la qualité du signal bien mieux qu’un filtre linéaire classique.
Cas 4 — Génération de contenus créatifs
Les autoencodeurs variationnels (VAE) étendent le concept en imposant une distribution probabiliste sur l’espace latent (généralement une gaussienne). Cette structure permet de générer de nouvelles données en échantillonnant dans l’espace latent et en passant par le décodeur. Applications : génération de visages, création musicale, design de molécules pharmaceutiques, ou interpolation créative entre deux concepts.
Conclusion
Les autoencodeurs représentent une méthode de réduction de dimensionalité non linéaire puissante et flexible. Là où l’ACP se limite aux combinaisons linéaires, les autoencodeurs capturent des relations complexes grâce à leurs couches non linéaires et leur architecture flexible. Ils sont particulièrement adaptables : la même idée encodeur-goulot-décodeur se décline en autoencodeur débruiteur, autoencodeur sparse, autoencodeur variationnel, et bien d’autres variantes.
Pour débuter, commencez par un autoencodeur simple sur MNIST avec Keras, comme montré dans les exemples ci-dessus. Expérimentez avec différentes tailles de goulot et architectures pour comprendre le compromis compression/fidélité. Puis explorez les variantes (débruiteur, convolutionnel, variationnel) selon votre application.
Voir aussi
- Structures de données avancées en Python : Dictionnaires et Ensembles
- Maîtriser l’Échange de Compteurs en Python : Guide Complet et Astuces

