GAT — Réseaux d’Attention sur Graphes
Résumé
Le GAT (Graph Attention Network) est une architecture de réseaux de neuronaux profonds spécialement conçue pour traiter des données structurées sous forme de graphes. Introduit par Veličković et al. en 2018, le GAT résout une limitation majeure des modèles précédents comme le GCN (Graph Convolutional Network) : au lieu d’accorder la même importance à tous les voisins d’un noeud, le GAT apprend à attribuer un poids d’attention différencié à chaque voisin, en fonction de la pertinence de la relation.
Concrètement, le mécanisme d’attention permet au réseau de déterminer automatiquement quels voisins sont les plus informatifs pour mettre à jour la représentation d’un noeud donné. Cette flexibilité permet au GAT d’induire sur des graphes de toute topologie, y compris les graphes orientés, et de traiter efficacement des graphes inductifs (généralisation à des noeuds jamais vus pendant l’entraînement).
Le GAT repose sur plusieurs innovations clés : le calcul des coefficients d’attention par paires de noeuds voisins via une couche LeakyReLU, la normalisation par softmax pour obtenir des poids comparables, l’agrégation pondérée des représentations voisines, et l’attention multi-têtes pour stabiliser l’apprentissage et capturer différentes relations simultanément.
Les applications du GAT sont extrêmement variées : classification de documents dans des réseaux de citations (comme le jeu de données Cora), détection de fraudes dans des réseaux financiers, prédiction de propriétés moléculaires en chimie computationnelle, ou encore recommandation sociale dans les plateformes en ligne. Ce guide explore en détail le fonctionnement mathématique, l’implémentation Python avec PyTorch, les hyperparamètres critiques, ainsi que les avantages et limites de cette architecture fondamentale du deep learning sur graphes.
Principe Mathématique du GAT
Le mécanisme d’attention du GAT repose sur un calcul local entre chaque noeud et ses voisins directs. Voici les étapes mathématiques fondamentales :
1. Transformation Linéaire Initiale
Pour chaque noeud i du graphe, on commence par appliquer une transformation linéaire paramétrée par une matrice de poids W :
Whᵢ = W · hᵢ
où hᵢ ∈ ℝᶠ est le vecteur de représentation du noeud i (de dimension f), et W ∈ ℝᶠ’ˣᶠ est une matrice apprise pendant l’entraînement. Cette transformation projette les caractéristiques des noeuds dans un nouvel espace de représentation.
2. Calcul des Coefficients d’Attention bruts
Pour chaque paire de noeuds voisins (i, j), on calcule un score d’attention brut eᵢⱼ :
eᵢⱼ = LeakyReLU(aᵀ · [Whᵢ || Whⱼ])
où :
– || désigne la concaténation des deux vecteurs transformés,
– a ∈ ℝ²ᶠ’ est un vecteur d’attention appris,
– aᵀ · [Whᵢ || Whⱼ] est un produit scalaire entre le vecteur d’attention et le vecteur concaténé,
– LeakyReLU est la fonction d’activation LeakyReLU avec un paramètre de pente négative (negative_slope), généralement fixé à 0,2.
L’utilisation de la concaténation [Whᵢ || Whⱼ] plutôt que la simple somme Whᵢ + Whⱼ est une décision architecturale cruciale : elle permet au réseau de capturer des interactions non symétriques entre les noeuds, ce qui est essentiel pour les graphes orientés.
3. Normalisation par Softmax
Les scores bruts sont normalisés par un softmax sur l’ensemble des voisins du noeud i :
αᵢⱼ = softmaxⱼ(eᵢⱼ) = exp(eᵢⱼ) / Σ_{k ∈ N(i)} exp(eᵢₖ)
où N(i) désigne l’ensemble des voisins du noeud i, y compris le noeud lui-même (grâce à l’ajout de self-loops). Cette normalisation garantit que les coefficients d’attention αᵢⱼ forment une distribution de probabilité : chaque coefficient est compris entre 0 et 1, et leur somme vaut 1 pour un noeud donné.
4. Agrégation Pondérée
La nouvelle représentation du noeud i est obtenue en agrégeant les représentations transformées de ses voisins, pondérées par les coefficients d’attention :
hᵢ’ = σ( Σ_{j ∈ N(i)} αᵢⱼ · Whⱼ )
où σ est une fonction d’activation non linéaire (généralement ELU dans l’implémentation originale). Cette étape produit la représentation mise à jour du noeud, intégrant l’information de son voisinage local avec des poids adaptatifs.
5. Attention Multi-Têtes
Pour stabiliser l’apprentissage et permettre au modèle de capturer différents types de relations, le GAT utilise un mécanisme d’attention multi-têtes. On exécute K têtes d’attention indépendantes en parallèle, chacune avec ses propres paramètres Wₖ et aₖ.
Pour les couches cachées du réseau, on concatène les sorties des K têtes :
hᵢ’ = ||{k=1}^{K} σ( Σ αᵢⱼ⁽ᵏ⁾ · Wₖhⱼ )
Cette concaténation multiplie la dimension de sortie par K. Pour la couche finale (couche de sortie), on utilise généralement la moyenne des têtes plutôt que la concaténation :
hᵢ’ = σ( (1/K) Σ{k=1}^{K} Σ{j ∈ N(i)} αᵢⱼ⁽ᵏ⁾ · Wₖhⱼ )
Ce choix évite de multiplier la dimension de sortie, ce qui serait inutile pour la couche de classification finale.
6. GAT vs GCN : Comparaison Fondamentale
La différence cruciale entre le GAT et le GCN réside dans la manière dont les contributions des voisins sont pondérées :
- GCN : utilise une pondération fixe basée sur les degrés des noeuds (1/√(dᵢ·dⱼ)). Cette pondération est symétrique et ne dépend pas des caractéristiques des noeuds.
- GAT : utilise une pondération apprise (αᵢⱼ = softmax(eᵢⱼ)) qui dépend des caractéristiques des deux noeuds impliqués. Cette pondération est potentiellement asymétrique.
Le GCN utilise une pondération symétrique fixe qui ne permet pas de distinguer l’importance relative des différents voisins. Le GAT, en revanche, apprend cette pondération de manière différentiable, ce qui lui confère une bien plus grande capacité d’expression. De plus, le GAT supporte les graphes orientés et la généralisation inductive, alors que le GCN est limité aux graphes non orientés et à l’approche transductive.
7. Variante GATv2
En 2021, les mêmes auteurs ont proposé GATv2, une amélioration du mécanisme d’attention original. Dans le GAT initial, le calcul du score d’attention est statique : le classifieur linéaire aᵀ · [Whᵢ || Whⱼ] ne dépend pas de la structure du graphe de manière non linéaire, ce qui limite l’expressivité. GATv2 résout ce problème en appliquant une transformation non linéaire avant le produit scalaire avec l’attention :
eᵢⱼ = aᵀ · LeakyReLU(Wₐ [Whᵢ || Whⱼ])
Cette inversion de l’ordre des opérations — non-linéarité avant le produit scalaire, plutôt qu’après — rend le mécanisme d’attention universellement expressif, capable de représenter n’importe quelle fonction d’attention sur les paires de noeuds.
Intuition : Pourquoi l’Attention sur Graphes est Puissante
Imaginez que vous assistez à une réunion d’équipe où plusieurs experts discutent d’un problème technique complexe. Chaque participant possède des connaissances différentes et variées.
Avec le GCN, vous écouteriez tout le monde de manière égale, indépendamment de leur expertise. Le junior qui vient de commencer reçoit le même poids d’écoute que le senior avec 20 ans d’expérience. C’est simple, mais ce n’est pas optimal.
Avec le GAT, vous apprenez progressivement à qui accorder plus d’attention. Vous réalisez que Sophie est une experte en sécurité informatique, donc quand le sujet touche à la sécurité, vous lui accordez un coefficient d’attention élevé (α ≈ 0,4). Marc est excellent en architecture système, donc pour les questions d’infrastructure, son poids d’attention augmente (α ≈ 0,35). D’autres collègues, moins pertinents pour le sujet du jour, reçoivent des coefficients plus faibles (α ≈ 0,05).
Et surtout, ces coefficients ne sont pas fixes : ils s’adaptent au contexte de chaque discussion. Pour un problème de base de données, ce n’est plus Sophie la plus écoutée, mais peut-être David, l’expert en systèmes distribués. Cette capacité d’adaptation contextuelle est exactement ce que le GAT reproduit mathématiquement.
L’Analogie du Détective
Un autre exemple éclairant : imaginez un détective qui enquête sur un réseau de suspects.
Avec le GCN, le détective interrogerait chaque contact du suspect principal avec la même intensité, indépendamment du fait que certains soient des connaissances superficielles et d’autres des complices proches.
Avec le GAT, le détective évalue chaque relation individuellement. Il accorde plus d’attention aux contacts fréquents (coefficients d’attention élevés), analyse la nature de chaque lien (la concaténation [Whᵢ || Whⱼ] capture la relation spécifique entre deux noeuds), et ajuste son interrogatoire en fonction de ce qu’il découvre. Si un contact se révèle être une impasse, le détective réduit automatiquement l’attention qu’il lui porte (le softmax attribue un faible coefficient α).
Cette capacité à hiérarchiser l’information selon sa pertinence contextuelle est exactement ce qui rend le GAT si puissant pour les données structurées en graphes. Le réseau « apprend » quels voisins sont importants pour chaque tâche spécifique, sans intervention humaine.
Implémentation Python avec PyTorch
Voici une implémentation complète d’un graphe attentionnel avec PyTorch, illustrant chaque composant du mécanisme d’attention décrit précédemment.
Couche GAT Individuelle
import torch
import torch.nn as nn
import torch.nn.functional as F
class GATLayer(nn.Module):
"""
Couche unique de Graph Attention Network.
Calcule les coefficients d'attention entre voisins et agrège les représentations.
"""
def __init__(self, in_features, out_features, dropout=0.6,
alpha=0.2, concat=True):
super(GATLayer, self).__init__()
self.dropout = dropout
self.in_features = in_features
self.out_features = out_features
self.alpha = alpha # paramètre negative_slope du LeakyReLU
self.concat = concat
# Matrice de transformation linéaire W
self.W = nn.Parameter(torch.empty(size=(in_features, out_features)))
nn.init.xavier_uniform_(self.W.data, gain=1.414)
# Vecteur d'attention a (décomposé en a_left et a_right pour l'efficacité)
self.a = nn.Parameter(torch.empty(size=(2 * out_features, 1)))
nn.init.xavier_uniform_(self.a.data, gain=1.414)
self.leakyrelu = nn.LeakyReLU(self.alpha)
def forward(self, h, adj):
"""
Forward pass de la couche GAT.
Arguments :
h : tenseur des caractéristiques des noeuds [N, in_features]
adj : matrice d'adjacence [N, N] (binaire ou pondérée)
Retour :
h_prime : nouvelles représentations des noeuds
attention : coefficients d'attention alpha_ij
"""
# Transformation linéaire : Wh pour tous les noeuds
Wh = torch.mm(h, self.W) # [N, out_features]
N = Wh.size()[0]
# Calcul des scores d'attention pour toutes les paires
# On décompose a en deux parties pour utiliser l'addition broadcast
a_input_left = torch.matmul(Wh, self.a[:self.out_features, :]) # [N, 1]
a_input_right = torch.matmul(Wh, self.a[self.out_features:, :]) # [N, 1]
# e_ij = LeakyReLU(a_left·Wh_i + a_right·Wh_j)
e = self.leakyrelu(a_input_left + a_input_right.T) # [N, N]
# Masque : on ne garde que les connexions existantes dans le graphe
mask = torch.zeros_like(e)
mask = mask.masked_fill(adj == 0, float('-inf'))
e = e + mask # les connexions inexistantes reçoivent -inf
# Normalisation par softmax sur les voisins de chaque noeud
attention = F.softmax(e, dim=1) # [N, N]
# Application du dropout sur les coefficients d'attention
attention = F.dropout(attention, self.dropout, training=self.training)
# Agrégation pondérée : h_i' = sigma(sum alpha_ij * Wh_j)
h_prime = torch.matmul(attention, Wh) # [N, out_features]
if self.concat:
return F.elu(h_prime), attention
else:
return h_prime, attention
def extra_repr(self):
return f'in_features={self.in_features}, out_features={self.out_features}, alpha={self.alpha}'
Modèle GAT à Deux Couches
class GAT(nn.Module):
"""
Modèle GAT complet avec deux couches et attention multi-têtes.
"""
def __init__(self, nfeat, nhid, nclass, dropout=0.6, alpha=0.2,
nheads=8):
"""
Arguments :
nfeat : dimension des caractéristiques d'entrée
nhid : dimension cachée par tête d'attention
nclass : nombre de classes en sortie
dropout : taux de dropout
alpha : pente négative du LeakyReLU
nheads : nombre de têtes d'attention
"""
super(GAT, self).__init__()
self.dropout = dropout
# Couche cachée : multi-têtes avec concaténation
# La sortie a donc une dimension de nheads * nhid
self.attentions = nn.ModuleList([
GATLayer(nfeat, nhid, dropout=dropout, alpha=alpha, concat=True)
for _ in range(nheads)
])
# Couche de sortie : une seule tête avec moyenne (pas de concaténation)
self.out_att = GATLayer(nhid * nheads, nclass, dropout=dropout,
alpha=alpha, concat=False)
def forward(self, x, adj):
"""
Forward pass du modèle GAT.
Arguments :
x : caractéristiques des noeuds [N, nfeat]
adj : matrice d'adjacence [N, N]
Retour :
logits : scores de classification pour chaque noeud [N, nclass]
"""
# Couche cachée : concaténation des têtes multiples
x = torch.cat([att(x, adj)[0] for att in self.attentions], dim=1)
x = F.dropout(x, self.dropout, training=self.training)
# Couche de sortie : moyenne des têtes
x, attention = self.out_att(x, adj)
return F.log_softmax(x, dim=1), attention
Boucle d’Entraînement sur Cora
import torch.optim as optim
from torch_geometric.datasets import Planetoid
# Chargement du jeu de données Cora (classification de documents scientifiques)
dataset = Planetoid(root='/tmp/Cora', name='Cora')
data = dataset[0] # un seul graphe
# Conversion de l'edge_index en matrice d'adjacence dense
N = data.num_nodes
adj = torch.zeros(N, N)
row, col = data.edge_index
adj[row, col] = 1.0
# Ajout des self-loops (chaque noeud est son propre voisin)
adj += torch.eye(N)
# Initialisation du modèle
model = GAT(
nfeat=data.num_features, # 1433 caractéristiques par document (sac de mots)
nhid=8, # 8 dimensions cachées par tête
nclass=dataset.num_classes, # 7 classes thématiques
dropout=0.6,
alpha=0.2,
nheads=8 # 8 têtes d'attention
)
# Optimiseur Adam avec régularisation L2
optimizer = optim.Adam(model.parameters(), lr=0.005, weight_decay=5e-4)
def accuracy(output, labels):
"""Calcule la précision de classification."""
preds = output.max(1)[1].type_as(labels)
correct = preds.eq(labels).double()
correct = correct.sum()
return correct / len(labels)
def train(epoch):
"""Une epoch d'entraînement du GAT sur Cora."""
model.train()
optimizer.zero_grad()
# Forward pass
output, attention = model(data.x, adj)
# Perte : entropie croisée négative sur les noeuds d'entraînement
loss = F.nll_loss(output[data.train_mask], data.y[data.train_mask])
# Précision sur les noeuds d'entraînement
acc = accuracy(output[data.train_mask], data.y[data.train_mask])
# Rétropropagation
loss.backward()
optimizer.step()
if epoch % 50 == 0:
print(f'Epoch {epoch:04d} | Loss: {loss.item():.4f} | '
f'Train Acc: {acc:.4f}')
# Entraînement
print("Début de l'entraînement du GAT sur Cora...")
for epoch in range(1, 1001):
train(epoch)
# Évaluation finale
model.eval()
with torch.no_grad():
output, attention = model(data.x, adj)
train_acc = accuracy(output[data.train_mask], data.y[data.train_mask])
val_acc = accuracy(output[data.val_mask], data.y[data.val_mask])
test_acc = accuracy(output[data.test_mask], data.y[data.test_mask])
print(f"\nRésultats finaux du GAT sur Cora :")
print(f" Précision entraînement : {train_acc:.4f}")
print(f" Précision validation : {val_acc:.4f}")
print(f" Précision test : {test_acc:.4f}")
Hyperparamètres Critiques du GAT
Le choix des hyperparamètres influence considérablement les performances du GAT. Voici les paramètres les plus importants et leurs valeurs recommandées :
Nombre de têtes d’attention (num_heads)
C’est l’hyperparamètre le plus structurant du GAT. Il détermine combien de mécanismes d’attention indépendants sont exécutés en parallèle.
- Couches cachées : 8 têtes est la valeur standard recommandée par les auteurs. Chaque tête capture un aspect différent des relations entre noeuds. Avec concaténation, la dimension de sortie est multipliée par K.
- Couche de sortie : généralement 1 seule tête, avec une moyenne au lieu de la concaténation. Cela évite de gonfler inutilement la dimension de sortie.
- Expérience : on peut réduire à 4 têtes pour des graphes plus petits ou augmenter à 16 pour des problèmes très complexes. Au-delà, les gains marginaux diminuent rapidement.
Dropout
Le dropout est appliqué à deux endroits dans le GAT : sur les coefficients d’attention et sur les représentations intermédiaires.
- Valeur typique : 0,6 pour la couche d’entrée, 0,4 pour la couche cachée.
- Rôle : empêche le surapprentissage (overfitting) en forçant le réseau à ne pas dépendre excessivement de certains voisins spécifiques. Sans dropout, le GAT a tendance à surapprendre les noeuds d’entraînement.
Pente négative du LeakyReLU (negative_slope / alpha)
Ce paramètre contrôle la partie négative de la fonction LeakyReLU utilisée dans le calcul des scores d’attention.
- Valeur standard : α = 0,2 (recommandée par les auteurs).
- Impact : une valeur trop faible rend le modèle moins expressif, une valeur trop élevée peut introduire du bruit dans les coefficients d’attention.
Taux d’apprentissage (learning rate)
Comme pour la plupart des architectures profondes, le taux d’apprentissage contrôle la vitesse de convergence.
- Pour Adam : lr = 0,005 est une bonne valeur de départ pour le GAT.
- Range typique : entre 0,001 et 0,01. Trop élevé, le modèle diverge ; trop bas, la convergence est excessivement lente.
- Avec ReduceLROnPlateau : on peut utiliser un scheduler pour réduire le taux d’apprentissage de facteur 0,5 quand la perte n’améliore plus pendant 50 epochs.
Régularisation L2 (weight_decay)
La régularisation L2 (ridge) pénalise les poids importants de la matrice W et du vecteur d’attention a.
- Valeur typique : 5 × 10⁻⁴ (0,0005).
- Importance : particulièrement cruciale pour le GAT car le mécanisme d’attention a beaucoup de paramètres (W, a pour chaque tête). Sans régularisation, le modèle surapprend rapidement.
Dimension cachée (hidden size)
- Standard : 8 à 64 par tête d’attention.
- Équilibre : une dimension plus grande augmente la capacité d’expression mais aussi le risque de surapprentissage. Le GAT compense souvent une dimension cachée réduite par le nombre de têtes d’attention.
Avantages du GAT
1. Pondération Adaptative des Voisins
Le principal avantage du GAT est sa capacité à apprendre dynamiquement l’importance de chaque voisin. Contrairement au GCN qui utilise une pondération fixe basée sur les degrés des noeuds, le GAT calcule un coefficient d’attention unique pour chaque paire (noeud, voisin). Cela signifie que deux noeuds différents accordent des poids différents au même voisin, reflétant la réalité que l’importance d’un voisin dépend du noeud qui l’observe. Cette adaptabilité se traduit par des performances supérieures sur de nombreuses tâches, avec une amélioration typique de 1 à 3 points de précision par rapport au GCN sur le benchmark Cora.
2. Support des Graphes Orientés
Grâce à l’utilisation de la concaténation [Whᵢ || Whⱼ] plutôt que de la somme symétrique Whᵢ + Whⱼ, le GAT capture naturellement les relations asymétriques. Par exemple, dans un réseau social où A suit B mais B ne suit pas A, le coefficient d’attention α{A→B} peut être très différent de α{B→A}. Cette propriété est essentielle pour modéliser des graphes de citations, des réseaux de transactions financières, ou des graphes de dépendance entre modules logiciels.
3. Généralisation Inductive
Le GAT ne dépend pas de la structure globale du graphe pour calculer les coefficients d’attention — tout est local (noeud + voisins immédiats). Cette propriété permet au GAT de généraliser à des noeuds jamais vus pendant l’entraînement, contrairement au GCN spectral qui nécessite de connaître l’ensemble du graphe. C’est un avantage décisif pour les applications en temps réel où de nouveaux noeuds apparaissent continuellement (nouveaux utilisateurs dans un réseau social, nouvelles molécules dans une base de données chimiques).
4. Interprétabilité des Coefficients d’Attention
Les coefficients αᵢⱼ sont directement accessibles après un forward pass, offrant une fenêtre d’interprétabilité rare dans le domaine du deep learning. En visualisant la matrice d’attention, on peut comprendre quelles relations le modèle considère comme importantes. Par exemple, dans un graphe de documents scientifiques, on peut identifier quels articles sont les plus influents pour la classification d’un document donné. Cette transparence est précieuse pour les applications sensibles (médical, juridique, financier).
5. Complexité Linéaire et Parallélisabilité
La complexité du calcul d’attention est O(|E|·F’) par couche, où |E| est le nombre d’arêtes et F’ la dimension cachée. C’est linéaire en fonction de la taille du graphe, ce qui rend le GAT applicable à des graphes de grande taille. De plus, toutes les opérations sont parallélisables sur GPU : le calcul des scores d’attention pour toutes les paires de noeuds connectés peut être effectué en une seule opération matricielle, comme démontré dans l’implémentation PyTorch ci-dessus.
Limites du GAT
1. Coût Mémoire Élevé pour les Grands Graphes
Bien que la complexité computationnelle soit linéaire, le besoin mémoire pour stocker la matrice d’attention est proportionnel au nombre d’arêtes pour une couche, et au carré du nombre de noeuds dans l’implémentation naïve avec matrice d’adjacence dense. Pour des graphes avec des millions de noeuds, cette approche devient impraticable. Des techniques comme le sparse attention ou le neighbor sampling sont nécessaires à cette échelle, mais elles ajoutent de la complexité.
2. Sensibilité aux Hyperparamètres
Le GAT possède plus d’hyperparamètres sensibles que le GCN : nombre de têtes, taux de dropout, pente négative du LeakyReLU, dimension cachée par tête, et l’architecture des têtes (combien par couche). La recherche de la configuration optimale peut être longue et coûteuse en ressources computationnelles. Un mauvais réglage des coefficients d’attention peut mener à un phénomène d’effondrement où une seule tête domine, rendant les autres têtes inutiles.
3. Limitation au Voisinage Local Immédiat
Comme le GCN, le GAT standard n’agrège que les voisins directs (1-hop). Pour capturer des informations plus éloignées, il faut empiler plusieurs couches, ce qui entraîne un phénomène de sur-lissage (over-smoothing) : au-delà de 2 à 3 couches, les représentations de tous les noeuds tendent à converger vers des vecteurs similaires. Des techniques comme les connections résiduelles, les skip connections, ou l’utilisation de sauts (Jumping Knowledge Networks) sont nécessaires pour atténuer ce problème.
4. Surapprentissage sur les Petits Graphes
Sur des graphes de petite taille (quelques centaines de noeuds), le GAT a tendance à surapprendre plus facilement que le GCN car il possède significativement plus de paramètres (matrices W et vecteurs d’attention a pour chaque tête). Même avec un dropout agressif de 0,6, le risque de surajustement aux noeuds d’entraînement est élevé. C’est particulièrement problématique pour les jeux de données de benchmark académiques comme Cora, CiteSeer ou PubMed, où seule une petite fraction des noeuds est utilisée pour l’entraînement.
Cas d’Usage concrets
1. Classification de Documents sur Cora
Le jeu de données Cora est le benchmark standard pour les réseaux de neuronaux sur graphes. Il contient 2 708 publications scientifiques en machine learning, reliées par 5 429 citations. Chaque document est représenté par un vecteur sac-de-mots de 1 433 dimensions et est étiqueté dans l’une des 7 catégories thématiques (réseaux de neuronaux, théorie de l’apprentissage, systèmes multi-agents, etc.).
Le GAT atteint typiquement une précision de 83,0 % à 83,8 % sur l’ensemble de test de Cora, surpassant le GCN qui obtient environ 81,5 %. L’amélioration vient de la capacité du GAT à attribuer des poids d’attention plus élevés aux citations pertinentes (par exemple, un document sur les réseaux de neuronaux récurrents accorde plus d’attention aux citations d’articles sur les RNN qu’aux articles sur les SVM).
# Exemple d'interprétation des coefficients d'attention sur Cora
# Après l'entraînement, on peut visualiser les poids d'attention
# pour comprendre quelles citations sont les plus importantes
import matplotlib.pyplot as plt
# Récupération de la matrice d'attention de la première tête
_, attention_weights = model(data.x, adj)
attention_np = attention_weights[0].detach().numpy()
# Pour un document donné, visualiser ses 5 citations les plus importantes
doc_idx = 42 # un document arbitraire
top_neighbors = attention_np[doc_idx].argsort()[-5:][::-1]
for neighbor_idx in top_neighbors:
if attention_np[doc_idx, neighbor_idx] > 0:
print(f"Document {doc_idx} → Document {neighbor_idx} "
f"(α = {attention_np[doc_idx, neighbor_idx]:.4f})")
2. Détection de Fraude dans les Réseaux Financiers
Dans le domaine de la détection de fraude, les transactions financières forment naturellement un graphe : les comptes sont des noeuds et les transactions sont des arêtes. Le GAT est particulièrement adapté à cette tâche car :
- Les fraudeurs ont des comportements distinctifs : ils peuvent avoir des coefficients d’attention anormalement élevés vers certains comptes (comptes complices). Le mécanisme d’attention capture ces patterns automatiquement.
- Les relations sont orientées : un virement de A vers B n’est pas équivalent à un virement de B vers A. Le GAT gère naturellement cette asymétrie.
- L’interprétabilité des coefficients d’attention permet aux analystes de comprendre pourquoi une transaction est signalée comme frauduleuse.
Des systèmes industriels utilisant des architectures similaires au GAT (comme les systèmes anti-fraude de grandes banques et de plateformes de paiement) peuvent détecter des schémas frauduleux complexes avec une précision supérieure à 95 % sur les transactions suspectes.
3. Prédiction de Propriétés Moléculaires
En chimie computationnelle, les molécules sont naturellement modélisées comme des graphes : les atomes sont des noeuds et les liaisons chimiques sont des arêtes. Prédire les propriétés d’une molécule (toxicité, solubilité, activité biologique) est un problème fondamental pour la découverte de médicaments.
Dans ce contexte, le GAT offre un avantage crucial : tous les atomes voisins n’ont pas la même importance. Par exemple, pour prédire la toxicité d’une molécule, un groupement fonctionnel spécifique (comme un groupement nitro) est beaucoup plus informatif que la chaîne carbonée principale. Le mécanisme d’attention du GAT apprend à attribuer des poids plus élevés à ces atomes « clés », ce qui se traduit par des prédictions plus précises.
Les modèles basés sur l’attention sur graphes atteignent des performances compétitives sur les benchmarks de référence comme MoleculeNet, surpassant souvent les approches basées sur les fingerprints moléculaires traditionnels. L’interprétabilité des coefficients d’attention permet en plus aux chimistes d’identifier les sous-structures moléculaires responsables de certaines propriétés, guidant ainsi la conception rationnelle de nouveaux composés.
4. Recommandation Sociale
Les plateformes de recommandation (e-commerce, streaming, réseaux sociaux) peuvent utiliser le GAT pour améliorer la qualité des suggestions en exploitant les relations sociales entre utilisateurs.
Dans un graphe de recommandation sociale :
– Les utilisateurs et les articles (films, produits, chansons) sont des noeuds.
– Les arêtes lient les utilisateurs aux articles qu’ils ont appréciés et les utilisateurs entre eux s’ils sont connectés socialement.
– Le GAT apprend à pondérer l’influence de chaque ami sur les préférences d’un utilisateur. Par exemple, si vous et votre ami avez des goûts cinématographiques similaires, le coefficient d’attention entre vous deux sera élevé pour la recommendation de films. En revanche, pour la recommandation de livres, ce même ami pourrait recevoir un faible coefficient si vos goûts littéraires divergent.
Des architectures inspirées du GAT, comme GraphSAGE avec attention ou PinSAGE de Pinterest, sont utilisées en production par des entreprises comme Pinterest, Uber Eats, et Alibaba pour leurs systèmes de recommandation, traitant des graphes avec des milliards de noeuds et d’arêtes grâce à des techniques de partitionnement et d’échantillonnage de voisins.
Voir Aussi
- Calculer la Surface Minimale d’un Polygone Convexe en Grille avec Python
- Calcul des Sommes des Carrés des Diviseurs Unitaires en Python : Guide Complet et Code Optimisé

