L'attention hybride¶
48 couches linéaires, 16 couches complètes, et les dimensions réelles de chacune.
Pourquoi mélanger¶
L'attention classique relit tout l'historique à chaque jeton : son coût croît avec le carré de la longueur. À 262 144 jetons, c'est prohibitif — et cela produit un cache clé-valeur qui grossit sans fin.
L'attention linéaire remplace cette relecture par un état de taille fixe, mis à jour jeton après jeton. Coût linéaire, mémoire constante — mais le rappel exact d'un détail lointain s'y dégrade.
La solution retenue par toute la génération 3.8 est de mélanger : les couches linéaires font le gros du travail, les couches complètes fournissent l'ancrage.
Le mécanisme conceptuel
Il est expliqué en détail, sans prérequis, dans Attention linéaire et DeltaNet.
Ce chapitre en donne la réalisation concrète dans ce modèle-ci.
Les 48 couches Gated DeltaNet¶
"linear_num_value_heads": 48,
"linear_num_key_heads": 16,
"linear_key_head_dim": 128,
"linear_value_head_dim": 128,
"linear_conv_kernel_dim": 4,
"output_gate_type": "swish",
"mamba_ssm_dtype": "float32"
Les dimensions dérivées¶
Le décompte¶
| Composant | Dimensions | Paramètres |
|---|---|---|
in_proj_qkvz — produit \(q\), \(k\), \(v\) et la porte \(z\) |
\(5\,120 \times (2\,048 + 2\,048 + 6\,144 + 6\,144)\) | 83 886 080 |
in_proj_ba — produit \(\beta\) et \(\alpha\), un par tête de valeur |
\(5\,120 \times 96\) | 491 520 |
| convolution causale, noyau 4 | \((2\,048 + 2\,048 + 6\,144) \times 4\) | 40 960 |
out_proj |
\(6\,144 \times 5\,120\) | 31 457 280 |
| normalisation | 128 | 128 |
| Total par couche | 115 875 968 | |
| × 48 couches | 5,562 G |
La dissymétrie 16 / 48
16 têtes de clé pour 48 têtes de valeur : trois têtes de valeur par tête de clé.
L'état récurrent de chaque tête est une matrice \(d_k \times d_v = 128 \times 128\). Réduire le nombre de têtes de clé réduit donc le nombre d'états à maintenir, sans amputer la richesse des valeurs.
Le Max pousse plus loin — 16 clés pour 128 valeurs, soit un rapport de 8. Ici le rapport n'est que de 3, ce qui est cohérent avec un modèle plus petit : moins de capacité, moins besoin de compresser.
La récurrence¶
Par tête, l'état \(S_t\) de dimension \(128 \times 128\) évolue selon :
| Symbole | Rôle |
|---|---|
| \(\alpha_t \in\, ]0,1[\) | décroissance globale — estompe tout l'état |
| \(\beta_t \in\, ]0,1[\) | taux d'écriture — remplace précisément l'association liée à \(\mathbf{k}_t\) |
| \(I\) | matrice identité \(128 \times 128\) |
Un tableau blanc : \(\alpha_t\) estompe légèrement tout ce qui est écrit, \(\beta_t\) efface une ligne précise et la réécrit.
L'état, en mémoire¶
Constant. Mille jetons ou un million, l'état pèse 159 Mo.
Le float32 n'est pas un détail
mamba_ssm_dtype: "float32", alors que tout le reste du modèle est en BF16.
L'état est une accumulation sur potentiellement un million de mises à jour multiplicatives ; en BF16, l'erreur d'arrondi s'accumulerait jusqu'à dégrader le rappel. C'est une contrainte à connaître si vous réimplémentez, et une ligne à ne pas « optimiser » par inadvertance.
Les 16 couches d'attention complète¶
"num_attention_heads": 24,
"num_key_value_heads": 4,
"head_dim": 256,
"attn_output_gate": true,
"partial_rotary_factor": 0.25,
"attention_bias": false,
"rope_parameters": { "rope_theta": 10000000, "mrope_interleaved": true }
Le décompte¶
| Projection | Dimensions | Paramètres |
|---|---|---|
| \(W_Q\) avec porte | \(5\,120 \times (24 \times 256 \times 2)\) | 62 914 560 |
| \(W_K\) | \(5\,120 \times (4 \times 256)\) | 5 242 880 |
| \(W_V\) | \(5\,120 \times (4 \times 256)\) | 5 242 880 |
| \(W_O\) | \((24 \times 256) \times 5\,120\) | 31 457 280 |
| normalisations \(q\), \(k\) | \(2 \times 256\) | 512 |
| Total par couche | 104 858 112 | |
| × 16 couches | 1,678 G |
Le facteur 2 sur \(W_Q\)
attn_output_gate: true : la projection des requêtes produit aussi la
porte de sortie, qui permet à la couche de s'annuler pour un jeton donné.
C'est la même convention que dans le Max. Sans ce facteur, le décompte final manquerait 0,5 G — un écart détectable sur la taille du dépôt.
GQA à 6:1¶
24 têtes de requête, 4 têtes clé-valeur. Chaque couple clé-valeur sert six requêtes.
Le cache par couche et par jeton :
Sans GQA — 24 têtes clé-valeur — ce serait 24 576 octets, soit six fois plus.
Le RoPE partiel¶
partial_rotary_factor: 0.25 : seules 64 des 256 dimensions de chaque tête
subissent la rotation positionnelle. Les 192 autres portent une information
sémantique non dégradée.
rope_theta: 10000000, contre 10 000 dans le Transformer d'origine. Cette base
élevée étale les fréquences et rend les positions distinguables sur des centaines
de milliers de jetons — condition nécessaire du contexte long.
La variante multimodale de ce RoPE est traitée au chapitre suivant.
Les deux types de couche, côte à côte¶
| Gated DeltaNet | Attention complète | |
|---|---|---|
| Nombre | 48 | 16 |
| Paramètres par couche | 115,9 M | 104,9 M |
| Total | 5,562 G | 1,678 G |
| Coût de calcul | \(O(n)\) | \(O(n^2)\) |
| Mémoire par séquence | constante (159 Mo au total) | croît : 4 096 o/jeton |
| Rappel exact à longue distance | dégradé | fiable |
Une couche DeltaNet coûte plus cher en paramètres, moins cher en tout le reste
115,9 M contre 104,9 M par couche — la couche linéaire est plus lourde, à cause de sa large projection d'entrée.
Mais elle ne produit aucun cache et son calcul est linéaire. Sur un contexte de 262 144 jetons, c'est ce qui fait toute la différence.
Détail chiffré : Contexte et cache.
À retenir¶
Ce chapitre en cinq points
- 48 couches Gated DeltaNet (5,562 G) et 16 couches d'attention complète (1,678 G).
- La dissymétrie 16 têtes de clé / 48 de valeur limite le nombre d'états récurrents à maintenir.
- L'état pèse 0,159 Go au total, indépendamment de la longueur, et est maintenu en float32.
- L'attention complète utilise GQA 6:1 et une porte de sortie, pour 4 096 octets de cache par couche et par jeton.
- RoPE partiel à 25 % avec une base de \(10^7\).
Chapitre suivant : La voie visuelle.