Réseaux Siamois : Guide complet — Similarité par Réseaux Jumeaux
Résumé — Les réseaux siamois (Siamese Networks) sont des architectures de deep learning conçues pour comparer des paires d’entrées et apprendre une mesure de similarité. Introduits par Bromley et al. en 1993 pour la vérification de signatures, ils consistent en deux sous-réseaux identiques (partageant les mêmes poids) qui transforment chaque entrée en un embedding, puis comparent ces embeddings via une fonction de distance. L’avantage clé: au lieu de classifier N catégories, le réseau apprend à dire “similaire ou différent”, ce qui fonctionne même pour des classes jamais vues pendant l’entraînement.
Principe mathématique
1. Architecture à poids partagés
Un réseau siamois est composé de deux branches identiques f_θ:
embed_1 = f_θ(x1)
embed_2 = f_θ(x2) # Mêmes paramètres θ
Les deux branches partagent exactement les mêmes poids: elles ne sont qu’un seul réseau appliqué deux fois.
2. Fonction de distance
La similarité entre x1 et x2 est mesurée par la distance euclidienne entre leurs embeddings:
d(x1, x2) = ||f_θ(x1) - f_θ(x2)||²
3. Contrastive Loss
La fonction de perte contrastive pousse les paires similaires à être proches et les dissimilaires à être éloignées:
L = y · d²
+ (1-y) · max(0, m - d)²
Où y = 1 si similaire et y = 0 si dissimilaire, et m est la marge (distance minimale désirée entre paires différentes). Le terme max(0, m – d)² signifie: si la distance dépasse déjà la marge, pas de pénalité. Sinon, on pénalise.
4. Triplet Loss
Une alternative populaire: le triplet loss prend un triplet (ancre, positif, négatif):
L = max(0, ||f(a) - f(p)||² - ||f(a) - f(n)||² + m)
L’ancre et le positif sont similaires (même classe), le négatif est différent. Le réseau apprend à rendre l’ancre plus proche du positif que du négatif, avec une marge m de séparation.
5. One-shot et few-shot learning
L’application la plus puissante des réseaux siamois: la reconnaissance avec un seul exemple. Si on a une seule photo de référence de chaque personne, on compare la nouvelle photo à toutes les références via la distance des embeddings:
classe(x_nouveau) = argmin_référence d(f(x_nouveau), f(référence))
Cela fonctionne pour des classes jamais vues pendant l’entraînement, car la fonction de similarité est générique, pas spécifique à une classe.
Intuition
Un réseau siamois, c’est comme un jumeau qui compare deux visages. Il ne reconnaît pas spécifiquement « c’est Pierre » ou « c’est Marie ». Il se demande juste: “est-ce que ces deux visages sont le même oui ou non?”.
C’est pourquoi c’est si puissant pour la reconnaissance avec un seul exemple: on n’a pas besoin de milliers de photos de chaque personne, juste d’une photo de référence et on compare. C’est la différence entre mémoriser un annuaire (classification classique) et savoir comparer deux personnes (réseau siamois).
Implémentation Python
1. Architecture siamoise with PyTorch
import torch
import torch.nn as nn
import torch.nn.functional as F
class SiameseNetwork(nn.Module):
"""Réseau siamois à deux branches partageant les mêmes poids."""
def __init__(self, input_dim=784, embed_dim=128):
super().__init__()
self.encoder = nn.Sequential(
nn.Linear(input_dim, 256), nn.ReLU(),
nn.Linear(256, 128), nn.ReLU(),
nn.Linear(128, embed_dim)
)
def forward_once(self, x):
return self.encoder(x)
def forward(self, x1, x2):
"""Retourne les embeddings des deux entrées."""
return self.forward_once(x1), self.forward_once(x2)
def contrastive_loss(embed1, embed2, label, margin=1.0):
"""Contrastive: label=1 si similaire, 0 si différent."""
dist = torch.sum((embed1 - embed2) ** 2, dim=1)
loss_pos = label * dist
loss_neg = (1 - label) * torch.max(
torch.zeros_like(dist),
(margin - torch.sqrt(dist + 1e-8)) ** 2
)
return (loss_pos + loss_neg).mean()
def triplet_loss(anchor, positive, negative, margin=0.3):
"""Triplet loss: ancre, positif, négatif."""
dist_pos = torch.sum((anchor - positive) ** 2, dim=1)
dist_neg = torch.sum((anchor - negative) ** 2, dim=1)
return torch.mean(torch.clamp(dist_pos - dist_neg + margin, min=0.0))
# Création et entraînement
model = SiameseNetwork(input_dim=784, embed_dim=64)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
for epoch in range(20):
model.train()
total_loss = 0
for x1, x2, labels in train_loader:
embed1, embed2 = model(x1.view(x1.size(0), -1), x2.view(x2.size(0), -1))
loss = contrastive_loss(embed1, embed2, labels, margin=1.0)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
avg = total_loss / len(train_loader)
print(f'Epoch {epoch} | Loss: {avg:.4f}')
2. Recherche par similarité
def find_similar(query, database, model, k=5):
"""Trouve les k plus similaires dans la base de données."""
model.eval()
with torch.no_grad():
q_embed = model.forward_once(query.view(1, -1))
d_embeds = model.forward_once(database)
distances = torch.sum((d_embeds - q_embed) ** 2, dim=1)
_, indices = torch.topk(distances, k, largest=False)
return indices.numpy()
# One-shot learning: tester sur un nouveau sujet
def one_shot_test(support_img, query_img, distractors, model):
"""Le modèle choisit l'image de même sujet parmi les distracteurs."""
candidates = torch.cat([query_img.unsqueeze(0), distractors], dim=0)
closest = find_similar(support_img, candidates, model, k=1)
return (closest[0] == 0) # La première est la bonne réponse
Hyperparamètres
| Hyperparamètre | Valeur typique | Description |
|---|---|---|
| margin | 0.3-1.0 | Distance maximale désirée pour les paires similaires |
| embed_dim | 64-512 | Dimension de l’espace d’embedding |
| learning_rate | 1e-4-1e-3 | Taux d’apprentissage |
| ratio_pos_neg | 1:3-1:5 | Ratio des paires similaires/dissimilaires |
Variantes et extensions
Réseaux siamois avec CNN
Pour les images, on remplace le MLP par un encodeur convolutionnel (plusieurs convolutions + pooling). Chaque branche est un CNN qui produit un embedding compact de l’image. L’architecture VGG ou ResNet pré-entraînée est souvent utilisée comme backbone.
Prototypical Networks
Une extension du concept siamois: au lieu de comparer à un seul exemple de référence, on calcule le prototype (moyenne des embeddings) de chaque classe dans le support set. La classification se fait par distance au prototype le plus proche.
Matching Networks
Utilisent un mécanisme d’attention pour pondérer les similarités entre la requête et chaque élément du support set. Plus sophistiqué que la simple distance euclidienne, surtout pour le few-shot learning avec plusieurs exemples par classe.
Avantages
- One-shot learning : Reconnaît des classes jamais vues avec un seul exemple de référence.
- Indépendant des classes : La fonction de similarité est générique, pas liée à un ensemble fixe de catégories.
- Ajout/suppression facile : Ajouter un nouveau sujet = une image de référence. Pas de réentraînement nécessaire.
- Applicabilité large : Images, texte, audio, signatures — tant qu’on peut construire des paires, ça fonctionne.
Limites
- Inférence coûteuse : Comparer une nouvelle entrée à toutes les références = O(N) embeddings et distances.
- Performance max inférieure : Sur un problème de classification standard avec beaucoup d’exemples, un classifieur classique bat souvent un réseau siamois.
- Qualité des paires critique : Le dataset de paires doit être bien équilibré et représentatif.
4 cas d’usage concrets
1. Vérification de signatures bancaires
L’application historique. Les banques comparent la signature d’un client sur un chèque avec sa référence. Le réseau siamois détecte les falsifications même lorsque les faussaires imitent habilement.
2. Reconnaissance faciale sur smartphone
FaceID d’Apple utilise un principe de similarité: l’empreinte faciale enregistrée (au setup) est comparée à la capture du visage. Si la distance des embeddings est suffisamment faible, le téléphone se déverrouille.
3. Recherche d’images par similarité visuelle
Google Images “rechercher par image”: on fournit une image de référence et le réseau siamois trouve les images les plus similaires visuellement dans un index de milliards de photos.
4. Détection de plagiat
Comparer des textes en les encodant via un réseau siamois (avec des embeddings de mots comme entrées) pour détecter les similarités sémantiques même quand le texte a été paraphrasé.
5. Recommandation de produits
Un réseau siamois peut apprendre à comparer les préférences de deux utilisateurs ou la similarité entre deux produits. Si un utilisateur A aime le produit X, le réseau recommande le produit Y le plus similaire à X dans l’espace d’embedding appris.
6. Réconciliation d’entités dans les bases de données
Quand deux bases de données contiennent des enregistrements sur les mêmes entités (clients, entreprises) mais avec des formats différents, un réseau siamois apprend à dire si deux enregistrements désignent la même entité réelle malgré les variations d’écriture.
Conclusion
Les réseaux siamois ont ouvert la voie à l’apprentissage de similarité par réseau neuronal. Leur principe fondamental — deux branches partageant les poids pour comparer des paires — est maintenant un élément standard du deep learning.
Les extensions modernes (triplet networks, contrastive pre-training pour les grands modèles de langage, prototypical networks) s’appuient tous sur la même idée centrale: apprendre une espace de représentation où la distance reflète la similarité sémantique.
Voir aussi
- Maîtriser les Produits Concatenés Pandigitaux avec Python : Guide Complet pour Développeurs en 2024
- Créer des Sous-ensembles à Somme Unique en Python : Guide Complet et Astuces Avancées

