Feed-Forward Network (FFN) : le moteur silencieux des Transformers et des LLM
Un réseau feed-forward (FFN, ou feedforward neural network) est un réseau de neurones dont l’information circule dans un seul sens, de l’entrée vers la sortie, sans boucle de rétroaction. C’est l’architecture neuronale la plus fondamentale en deep learning, et c’est aussi le composant qui concentre la majorité des paramètres dans chaque bloc Transformer.
- Alias
- FFN, FFNN, MLP (Multi-Layer Perceptron), réseau à propagation avant
- Type
- Architecture de réseau de neurones
- Flux de données
- Unidirectionnel (entrée → couches cachées → sortie)
- Rôle dans un Transformer
- Transformation non linéaire position par position après l’attention
- Part des paramètres
- ~⅔ des paramètres d’un bloc Transformer standard
- Variantes modernes
- SwiGLU (LLaMA, Mistral), GeGLU (Gemma), ReLU² (Nemotron)
- Papier fondateur
- Rosenblatt (1958), puis Vaswani et al. (2017) pour le rôle dans les Transformers
Qu’est-ce qu’un réseau feed-forward ?
Le terme « feed-forward » décrit le sens de circulation des données : l’information avance couche par couche, de l’entrée vers la sortie, sans jamais revenir en arrière. C’est la distinction fondamentale avec les réseaux récurrents (RNN), où des boucles permettent à la sortie d’influencer les entrées suivantes.
Concrètement, un réseau feed-forward est constitué de trois types de couches :
Couche d’entrée : elle reçoit les données brutes (vecteurs de caractéristiques, pixels, embeddings). Aucun calcul n’y est effectué, c’est un simple relais.
Couches cachées : une ou plusieurs couches de neurones appliquent des transformations successives. Chaque neurone calcule une somme pondérée de ses entrées, ajoute un biais, puis passe le résultat dans une fonction d’activation non linéaire (ReLU, GELU, Swish, etc.).
Couche de sortie : elle produit la prédiction finale, que ce soit une classe (classification), une valeur continue (régression), ou une distribution de probabilités sur un vocabulaire (modèle de langue).
Mathématiquement, pour un réseau à une couche cachée, la transformation s’écrit :
y = W₂ · σ(W₁ · x + b₁) + b₂
Où W₁ et W₂ sont les matrices de poids, b₁ et b₂ les biais, et σ la fonction d’activation. Cette formulation simple est exactement celle qu’on retrouve dans chaque bloc Transformer.
FFN vs MLP : quelle différence ?
Les deux termes sont souvent utilisés de manière interchangeable, mais il y a une nuance technique. Le feed-forward neural network (FFNN) est la catégorie générale : tout réseau où les données circulent dans un seul sens. Le Multi-Layer Perceptron (MLP) est un type spécifique de FFNN avec au moins une couche cachée et des fonctions d’activation non linéaires.
En d’autres termes : tous les MLP sont des FFN, mais tous les FFN ne sont pas des MLP. Un réseau linéaire à une seule couche (comme la régression linéaire) est techniquement un FFN, mais pas un MLP. Les réseaux convolutifs (CNN) sont aussi des FFN au sens large, car l’information n’y circule que dans un sens.
En pratique, dans le contexte des LLM et des Transformers, quand on parle de « la couche FFN » ou de « la couche MLP », c’est la même chose : le sous-réseau à deux couches linéaires avec activation non linéaire qui suit le mécanisme d’attention dans chaque bloc.
Bref historique : du perceptron aux Transformers
L’histoire des réseaux feed-forward est celle du deep learning lui-même. En 1958, Frank Rosenblatt propose le perceptron, un classifieur binaire à une seule couche. Il ne peut résoudre que des problèmes linéairement séparables (le fameux problème XOR lui résiste).
Dans les années 1980, la redécouverte de la rétropropagation permet d’entraîner des réseaux multicouches. Les MLP deviennent capables de résoudre des problèmes non linéaires. C’est aussi l’époque du théorème d’approximation universelle : un réseau avec une seule couche cachée, suffisamment de neurones et une activation non linéaire peut approximer n’importe quelle fonction continue sur un domaine borné.
Les années 2010 voient l’explosion du deep learning grâce aux GPU. Les FFN deviennent les briques de base de toutes les architectures : CNN pour la vision, RNN/LSTM pour les séquences, et finalement les Transformers à partir de 2017.
C’est le papier « Attention Is All You Need » (Vaswani et al., 2017) qui fige le rôle actuel du FFN : un sous-réseau position-wise à deux couches linéaires avec activation ReLU, appliqué après le mécanisme d’attention dans chaque bloc encoder et decoder.
Le rôle du FFN dans les Transformers
Dans un bloc Transformer, deux composants se succèdent : le mécanisme d’self-attention (qui mélange les informations entre positions de la séquence) et le réseau feed-forward (qui transforme chaque position indépendamment).
Le FFN agit comme un réseau « expand-and-contract » (expansion puis contraction) :
Première couche linéaire : elle projette chaque vecteur de dimension d_model (ex. 512, 768, 4096) vers un espace de dimension supérieure d_ff, généralement 4× d_model. Par exemple, dans le Transformer original, d_model = 512 et d_ff = 2048.
Fonction d’activation : une non-linéarité (ReLU dans le papier original, GELU dans BERT et GPT-2, SwiGLU dans les architectures récentes) est appliquée pour introduire de la capacité de représentation non linéaire.
Seconde couche linéaire : elle ramène le vecteur à la dimension originale d_model, permettant la connexion résiduelle et la suite du traitement.
La formule classique est :
FFN(x) = W₂ · ReLU(W₁ · x + b₁) + b₂
Le terme « position-wise » signifie que le même réseau (mêmes poids) est appliqué indépendamment à chaque position de la séquence. Le token à la position 3 est transformé exactement de la même manière que celui à la position 42. C’est l’attention qui s’occupe des relations entre positions ; le FFN, lui, enrichit la représentation de chaque token individuellement.
Le FFN concentre la majorité des paramètres
Un fait souvent sous-estimé : dans un bloc Transformer standard, le FFN contient plus de paramètres que le mécanisme d’attention. Pour un modèle avec d_model = 1024 et d_ff = 4096, le FFN a 2 × (1024 × 4096) = ~8,4 millions de paramètres par bloc, contre environ 4,2 millions pour l’attention multi-têtes. Le FFN représente donc environ deux tiers des paramètres entraînables d’un bloc Transformer.
Cette proportion explique pourquoi les recherches récentes s’intéressent autant à l’optimisation du FFN : c’est là que se trouve le plus gros levier d’amélioration en termes de performance et d’efficacité.
Le FFN comme mémoire de connaissances
Des travaux de recherche (notamment « Transformer Feed-Forward Layers Are Key-Value Memories » de Geva et al.) ont montré que les couches FFN fonctionnent comme des mémoires clé-valeur. La première couche associe des patterns d’entrée (clés) à des activations, et la seconde couche projette ces activations vers des sorties (valeurs).
En pratique, cela signifie que la majorité des connaissances factuelles d’un LLM sont stockées dans ses couches FFN. Quand un modèle « sait » que Paris est la capitale de la France, cette information est principalement encodée dans les poids de ses FFN, pas dans les couches d’attention. C’est aussi pourquoi les techniques d’édition de connaissances ciblent souvent spécifiquement les couches FFN.
Fonctions d’activation modernes : de ReLU à SwiGLU
L’évolution des fonctions d’activation dans les FFN des Transformers a été un axe majeur de progrès. Voici les étapes clés :
ReLU et GELU
Le Transformer original (2017) utilise ReLU : ReLU(x) = max(0, x). Simple, rapide, mais avec le problème des « neurones morts » (un neurone dont l’entrée est toujours négative ne produit jamais de gradient).
BERT (2018) et GPT-2 (2019) adoptent GELU (Gaussian Error Linear Unit), une activation plus lisse qui ne supprime pas complètement les valeurs négatives. GELU est définie comme GELU(x) = x · Φ(x), où Φ est la fonction de distribution cumulative de la gaussienne standard. Elle offre un meilleur flux de gradients et de meilleures performances empiriques.
SwiGLU : le standard actuel
SwiGLU (Swish-Gated Linear Unit), proposée par Noam Shazeer en 2020, est devenue la fonction d’activation dominante dans les LLM modernes. Elle est utilisée dans LLaMA, Mistral, PaLM, DeepSeek et la quasi-totalité des modèles de pointe.
Le principe : au lieu d’une simple activation, SwiGLU introduit un mécanisme de « gating » (porte) où une projection contrôle le flux d’information d’une autre projection :
SwiGLU(x) = (x · W₁) ⊙ Swish(x · Wg)
FFN_SwiGLU(x) = W₂ · SwiGLU(x)
Où ⊙ est le produit élément par élément et Swish(x) = x · σ(x) (σ étant la sigmoïde). Ce mécanisme de gating permet au réseau de contrôler dynamiquement quelles informations passent, offrant une expressivité supérieure.
d_ff = 4 × d_model, un FFN SwiGLU utilise d_ff = (8/3) × d_model, souvent arrondi au multiple de 256 le plus proche pour des raisons d’efficacité matérielle.
Comparaison des fonctions d’activation dans les FFN
| Activation | Formule simplifiée | Matrices de poids | Modèles notables | Verdict |
|---|---|---|---|---|
| ReLU | max(0, x) | 2 | Transformer original (2017) | Obsolète pour les LLM |
| GELU | x · Φ(x) | 2 | BERT, GPT-2, GPT-3 | Encore viable, en déclin |
| GeGLU | (xW₁) ⊙ GELU(xWg) | 3 | Gemma (Google) | Bon compromis |
| SwiGLU | (xW₁) ⊙ Swish(xWg) | 3 | LLaMA, Mistral, PaLM, DeepSeek | Standard actuel |
| ReLU² | (max(0, x))² | 2 | Nemotron-4 (NVIDIA) | Niche, sparsité élevée |
FFN et Mixture of Experts (MoE)
L’une des évolutions les plus marquantes autour du FFN est le Mixture of Experts (MoE). Le principe : remplacer le FFN unique et dense de chaque bloc Transformer par plusieurs FFN parallèles (les « experts »), avec un routeur qui dirige chaque token vers un sous-ensemble d’experts.
Par exemple, Mixtral 8x7B possède 8 experts FFN par couche, mais seuls 2 sont activés pour chaque token. Le modèle totalise environ 47 milliards de paramètres, mais n’en utilise que ~13 milliards par token à l’inférence. DeepSeek-V3 pousse le concept encore plus loin avec 256 experts routés et 1 expert partagé, pour un total de 671 milliards de paramètres.
Le MoE s’applique au FFN (et non à l’attention) pour une raison simple : le FFN traite chaque token indépendamment, ce qui le rend naturellement compatible avec un routage par token. L’attention, qui modélise les interactions entre tokens, se prête moins bien à ce découpage.
Recherche récente : le FFN sous le microscope
Redondance et partage de FFN
Des travaux d’Apple Research (« One Wide Feedforward is All You Need », 2024) ont montré que les FFN des Transformers contiennent une redondance significative. Les chercheurs ont réussi à supprimer les FFN des couches decoder et à partager un seul FFN élargi à travers l’encoder, obtenant des gains en précision et en latence par rapport au Transformer original.
FFN à trois couches
Un papier de 2025 (« Attention Is Not All You Need ») explore l’ajout d’une troisième couche linéaire dans le FFN des Transformers. Les résultats montrent qu’avec un budget de paramètres constant, un FFN plus profond (trois couches) peut surpasser un FFN à deux couches, confirmant que l’architecture du FFN reste un territoire fertile pour l’optimisation.
Stabilité d’entraînement : Smooth-SwiGLU
L’entraînement de modèles SwiGLU en précision réduite (FP8) pose des problèmes de stabilité. Des recherches récentes ont identifié un mécanisme où les poids de SwiGLU s’alignent progressivement, créant des activations quadratiques qui peuvent provoquer des divergences catastrophiques après des centaines de milliards de tokens. Des variantes comme Smooth-SwiGLU ont été proposées pour atténuer ce risque lors de l’entraînement à grande échelle.
Implémentation pratique en PyTorch
Voici une implémentation du FFN position-wise tel qu’il apparaît dans un Transformer, avec les trois variantes principales :
FFN classique (ReLU/GELU)
import torch
import torch.nn as nn
class FeedForward(nn.Module):
def __init__(self, d_model: int, d_ff: int, dropout: float = 0.1):
super().__init__()
self.w1 = nn.Linear(d_model, d_ff)
self.w2 = nn.Linear(d_ff, d_model)
self.dropout = nn.Dropout(dropout)
self.activation = nn.GELU()
def forward(self, x):
# x shape: (batch_size, seq_length, d_model)
x = self.w1(x) # -> (batch_size, seq_length, d_ff)
x = self.activation(x) # non-linearite
x = self.dropout(x)
x = self.w2(x) # -> (batch_size, seq_length, d_model)
return x
FFN avec SwiGLU
class SwiGLUFeedForward(nn.Module):
def __init__(self, d_model: int, d_ff: int, dropout: float = 0.1):
super().__init__()
# Trois matrices au lieu de deux
self.w1 = nn.Linear(d_model, d_ff, bias=False)
self.wg = nn.Linear(d_model, d_ff, bias=False) # gate
self.w2 = nn.Linear(d_ff, d_model, bias=False)
self.dropout = nn.Dropout(dropout)
def forward(self, x):
# Swish gating: SiLU(x·Wg) ⊙ (x·W1)
gate = torch.nn.functional.silu(self.wg(x))
x = gate * self.w1(x)
x = self.dropout(x)
x = self.w2(x)
return x
En production, les architectures comme LLaMA utilisent exactement ce pattern SwiGLU, avec une dimension cachée ajustée (typiquement d_ff = int(8/3 * d_model), arrondi au multiple de 256 le plus proche) pour compenser la troisième matrice de poids.
Applications concrètes des réseaux feed-forward
Au-delà des Transformers, les réseaux feed-forward interviennent dans de nombreux contextes :
Classification d’images : les couches « fully connected » en fin de CNN sont des FFN qui convertissent les features maps en prédictions de classes.
Systèmes de recommandation : les modèles de recommandation utilisent des FFN pour apprendre les interactions entre caractéristiques utilisateur et contenu.
Régression et prédiction : les FFN restent un choix solide pour les problèmes tabulaires, en concurrence avec les approches de type gradient boosting.
Couches de projection : dans les architectures multimodales, des FFN servent de « pont » pour aligner les représentations de différentes modalités (texte, image, audio) dans un même espace vectoriel.
Réseaux de politique en RL : les réseaux de politique et de valeur dans le reinforcement learning sont souvent de simples FFN.
Limites des réseaux feed-forward
Malgré leur omniprésence, les FFN ont des limites bien identifiées :
Pas de mémoire séquentielle : un FFN ne peut pas capturer les dépendances temporelles. Pour traiter des séquences, il faut le combiner avec de l’attention (Transformers) ou utiliser une architecture récurrente (RNN, LSTM).
Taille fixe des entrées : un FFN classique attend des entrées de dimension fixe. C’est la tokenisation et les embeddings qui gèrent la conversion de données de longueur variable en vecteurs de taille fixe.
Coût en paramètres : l’expansion 4× dans les Transformers rend le FFN gourmand en paramètres. C’est précisément ce problème que le MoE cherche à résoudre en activant sélectivement des sous-ensembles de paramètres.
Interprétabilité : comprendre ce que font exactement les couches FFN d’un LLM reste un défi de recherche actif. Malgré les progrès en mécanique interprétative, décoder les connaissances stockées dans des millions de poids reste complexe.
Termes associés à connaître
| Terme | Relation avec le FFN |
|---|---|
| Transformer | Architecture qui utilise le FFN comme composant central de chaque bloc |
| Self-Attention | Complément du FFN dans un bloc Transformer : mélange inter-positions vs transformation intra-position |
| Backpropagation | Algorithme d’entraînement qui propage les erreurs en sens inverse du flux feed-forward |
| Fonction d’activation | Non-linéarité appliquée entre les couches du FFN (ReLU, GELU, SwiGLU) |
| Mixture of Experts | Architecture qui remplace le FFN dense par plusieurs FFN experts avec routage |
| Dropout | Technique de régularisation couramment appliquée dans les couches FFN |
| Layer Normalization | Normalisation appliquée avant ou après le FFN dans un bloc Transformer |
Questions fréquentes sur le réseau feed-forward
Quelle est la différence entre un réseau feed-forward et un réseau récurrent ?
Un réseau feed-forward propage l’information dans un seul sens (entrée → sortie) sans boucle. Un réseau récurrent (RNN) possède des connexions de rétroaction qui permettent à la sortie d’une étape d’influencer l’étape suivante. Le FFN ne conserve aucune mémoire entre les entrées, tandis que le RNN maintient un état interne. Dans les Transformers, c’est le mécanisme d’attention (et non la récurrence) qui gère les dépendances entre positions, et le FFN se charge de la transformation individuelle de chaque position.
Pourquoi le FFN utilise-t-il SwiGLU au lieu de ReLU dans les LLM modernes ?
SwiGLU introduit un mécanisme de gating dynamique qui contrôle le flux d’information de manière plus fine que ReLU. En pratique, les modèles entraînés avec SwiGLU obtiennent de meilleures perplexités et de meilleurs scores sur les benchmarks aval, pour un coût de calcul comparable. Le mécanisme de porte (gating) permet au réseau de décider quelles combinaisons de features conserver ou atténuer, offrant une expressivité supérieure. C’est pourquoi LLaMA, Mistral, PaLM et la plupart des LLM de pointe l’ont adopté comme standard.
Combien de paramètres un FFN représente-t-il dans un LLM ?
Dans un bloc Transformer standard, le FFN contient environ deux tiers des paramètres. Pour un modèle comme LLaMA 2-7B avec d_model = 4096 et d_ff ≈ 11008 (SwiGLU), chaque couche FFN contient environ 3 × (4096 × 11008) ≈ 135 millions de paramètres, contre environ 67 millions pour l’attention. Multipliez par le nombre de couches (32 dans ce cas), et les FFN totalisent plus de 4 milliards de paramètres sur les 7 milliards du modèle.
Peut-on supprimer le FFN d’un Transformer ?
Des expériences ont montré qu’un Transformer sans FFN (zéro couche linéaire par bloc) subit une dégradation significative des performances. Le FFN n’est pas un composant optionnel : il apporte la transformation non linéaire indispensable à la capacité de représentation du modèle. Des travaux récents ont montré qu’il est possible de partager un FFN entre plusieurs couches, ou de réduire son nombre de paramètres, mais le supprimer complètement reste préjudiciable.
Quel est le lien entre FFN et Mixture of Experts (MoE) ?
Le MoE est une évolution directe du FFN. Au lieu d’un seul FFN dense appliqué à tous les tokens, le MoE place plusieurs FFN (les « experts ») en parallèle, avec un routeur qui dirige chaque token vers les 1 à 2 experts les plus pertinents. Cela permet d’augmenter massivement la capacité du modèle (paramètres totaux) tout en gardant un coût de calcul par token comparable à un FFN unique. Des modèles comme Mixtral 8x7B, DeepSeek-V3 ou Qwen3-30B-A3B utilisent cette approche.