Aller au contenu principal

Module 6 — GRU : une simplification efficace

Le LSTM est efficace mais coûteux. Le GRU (Gated Recurrent Unit) est une simplification proposée en 2014 qui atteint des performances comparables sur la majorité des tâches, avec 25 % de paramètres en moins et un temps par pas proportionnellement plus court. Ce module en donne l'équation, le compte des paramètres, et une comparaison honnête sur le fil rouge.

Deux portes au lieu de trois, un seul état

Le GRU fusionne deux idées du LSTM. D'abord, il élimine la distinction entre état de cellule et état caché : il ne garde qu'un seul vecteur hth_t. Ensuite, il combine la porte d'oubli et la porte d'entrée en une seule porte de mise à jour ztz_t. Une nouvelle porte, dite de réinitialisation rtr_t, contrôle combien de l'état précédent participe au candidat.

Les équations, dans l'ordre du calcul :

zt=σ(Wz[ht1,xt]+bz)z_t = \sigma(W_z [h_{t-1}, x_t] + b_z) rt=σ(Wr[ht1,xt]+br)r_t = \sigma(W_r [h_{t-1}, x_t] + b_r) h~t=tanh(Wh[rtht1,xt]+bh)\tilde{h}_t = \tanh(W_h [r_t \odot h_{t-1}, x_t] + b_h) ht=(1zt)ht1+zth~th_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t

La dernière ligne exprime la propriété clé : la mise à jour est une interpolation entre l'ancien état ht1h_{t-1} et le candidat h~t\tilde{h}_t, pilotée par ztz_t. Quand zt=0z_t = 0, l'état est conservé tel quel ; quand zt=1z_t = 1, il est intégralement remplacé.

Comparé au LSTM, on a économisé une porte (la porte de sortie) et un état (l'état de cellule). L'idée conceptuelle est identique : offrir un chemin où le gradient peut passer sans multiplication matricielle répétée, en remplaçant la mise à jour par une addition pondérée.

Compter les paramètres

Chaque transformation affine du GRU projette un vecteur de taille H+FH + F sur HH, avec un biais. Il y en a trois : WzW_z, WrW_r et WhW_h.

parameˋtres GRU=3(H(H+F)+H)=3H(H+F+1)\text{paramètres GRU} = 3 \cdot (H \cdot (H + F) + H) = 3H(H + F + 1)

Pour la consommation électrique avec F=1F = 1 et H=64H = 64 : 36466=126723 \cdot 64 \cdot 66 = 12\,672. À comparer aux 1689616\,896 du LSTM et aux 42244224 du RNN simple. Le GRU coûte 75 % de ce que coûte un LSTM à capacité cachée égale.

ArchitectureParamètres (F=1F=1, H=64H=64)Temps par pasRésultat typique
SimpleRNN4 224disparition rapide
GRU12 672comparable au LSTM
LSTM16 8962,5×référence historique

Le tableau explique pourquoi le GRU est le choix pragmatique par défaut : même famille de résultats que le LSTM pour un budget calcul et mémoire plus léger.

GRU en Keras

L'API est jumelle de celle du LSTM. Toutes les options (return_sequences, return_state, stateful, recurrent_dropout) existent sous le même nom.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

modele_gru = keras.Sequential([
layers.Input(shape=(168, 1)),
layers.GRU(64), # remplace LSTM(64)
layers.Dense(24),
])

modele_gru.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-3, clipnorm=1.0),
loss="mse",
metrics=["mae"],
)

Rien d'autre à changer dans le code d'entraînement. C'est ce qui permet de faire une comparaison honnête, en ne modifiant qu'une ligne.

Comparer sur le fil rouge

Sur la consommation électrique, on ne peut pas dire d'avance lequel des deux sera meilleur. La bonne pratique est de mesurer. Voici un cadre minimal, qui sera repris et étendu au module 10.

resultats = {}
for nom, cellule in [("gru", layers.GRU), ("lstm", layers.LSTM)]:
modele = keras.Sequential([
layers.Input(shape=(168, 1)),
cellule(64),
layers.Dense(24),
])
modele.compile(
optimizer=keras.optimizers.Adam(learning_rate=1e-3, clipnorm=1.0),
loss="mse",
metrics=["mae"],
)
modele.fit(
X_train, y_train,
validation_data=(X_val, y_val),
epochs=50,
batch_size=64,
callbacks=[keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True)],
verbose=0,
)
mae_test = modele.evaluate(X_test, y_test, verbose=0)[1]
resultats[nom] = mae_test

print(resultats)

Trois observations reviennent sur des tâches de prévision de moins de 200 pas : GRU et LSTM ont des scores comparables (à moins de 5 % l'un de l'autre), GRU entraîne 20 à 30 % plus vite par époque, et LSTM est un peu plus stable en fin d'entraînement grâce à son état de cellule séparé.

Quand préférer l'un à l'autre

Les recommandations qui suivent sont empiriques mais robustes.

Choisir GRU en premier sur une nouvelle tâche : c'est le plus simple à faire converger, le plus rapide à entraîner, et il servira de référence. Sur la consommation électrique du fil rouge, GRU est le point de départ.

Passer à LSTM quand :

  • la séquence dépasse plusieurs centaines de pas et le GRU sature ;
  • la tâche a une structure hiérarchique où l'état de cellule séparé aide (langage, code) ;
  • on empile plusieurs couches (module 7) et l'entraînement devient instable — le LSTM absorbe mieux les couches empilées.

Passer à autre chose (transformeur du cours 12) quand :

  • la séquence dépasse 1000 pas et le coût séquentiel devient rédhibitoire ;
  • l'entraînement doit se paralléliser sur la dimension temps ;
  • une attention entre les pas est nécessaire (module 8 en donne un aperçu).

Le rideau : ce que ni GRU ni LSTM ne font

Aucune de ces deux architectures ne résout complètement la disparition de gradient. Sur des séquences de plusieurs milliers de pas, elles finissent par échouer aussi. La différence avec le RNN simple est quantitative : là où un RNN plafonne à 10 ou 20 pas, un LSTM tient 300 à 500 pas honnêtement. Au-delà, il faut un mécanisme d'attention ou une architecture entièrement différente.

De même, la boucle temporelle reste séquentielle : le pas tt dépend du pas t1t - 1. Un accélérateur ne peut pas être mieux utilisé. Cette limitation est la raison d'être du cours 12.

La comparaison honnête demande le même budget de calcul

Comparer un LSTM de H=64H = 64 à un GRU de H=64H = 64 n'est pas juste : le LSTM a 33 % de paramètres en plus. Une comparaison à budget égal utilise un GRU de H=74H = 74 (qui a environ 16 900 paramètres), ce qui remet les résultats à leur place. Sur la plupart des tâches de séries temporelles, la différence finale entre les deux est alors nulle à un écart-type près.

Toujours faire tourner les deux

Le coût d'entraîner GRU et LSTM est le coût d'un seul plus 30 %. L'information gagnée — savoir lequel gagne sur votre tâche, avec quelle marge — vaut cent fois ce prix. C'est le premier test comparatif du module 10.

En résumé

  • Le GRU fusionne la porte d'oubli et la porte d'entrée du LSTM en une seule porte de mise à jour ztz_t et introduit une porte de réinitialisation rtr_t, avec un seul état hth_t au lieu de deux.
  • La mise à jour est une interpolation ht=(1zt)ht1+zth~th_t = (1 - z_t) h_{t-1} + z_t \tilde{h}_t : le chemin d'addition pour le gradient est préservé.
  • Le GRU coûte 75 % des paramètres et environ 80 % du temps par pas d'un LSTM à même HH ; à budget égal, les résultats sont statistiquement indistinguables.
  • Commencer par GRU ; passer à LSTM pour les séquences très longues, les tâches hiérarchiques ou les architectures empilées ; passer aux transformeurs quand la longueur ou le débit deviennent bloquants.

Module suivant : combiner plusieurs couches et regarder dans les deux directions du temps, quand le futur est disponible à l'entraînement mais pas à l'inférence.