Loading
En médiane, 24 % de chaque ligne affichée avait déjà été supprimée avant que vous ne la voyiez. Au pire, 95 %. L'arithmétique était juste depuis le début.
Ouvrir l'instrumentBERT ajoute deux tokens à chaque phrase qu'on lui donne. [CLS] au début, [SEP] à la fin. Ce sont des marqueurs — l'un signale le début, l'autre la fin — et aucun n'est un mot que vous avez écrit.
Ce sont aussi, dans beaucoup de têtes, l'endroit où va l'essentiel de l'attention.
Cela pose un problème à toute interface qui veut dessiner la phrase. On ne peut pas tracer d'arcs vers [SEP] : le visiteur ne l'a pas tapé et n'a aucune idée de ce que c'est. On supprime donc ces colonnes et on renormalise le reste pour que la ligne somme encore à 1.
C'est ce que faisait ce projet. L'arithmétique était correcte. La présentation était un mensonge.
L'idée décisive : si vous retirez une partie d'une distribution puis renormalisez, chaque nombre affiché devient une part d'un tout plus petit — et il est indiscernable d'une part du tout d'origine.
the → scissors 0,431 avait l'air d'une relation forte. Dans la tête d'où il venait, le poids réel était de 0,021. La valeur affichée était une part des 4,8 % de cette ligne ayant survécu à la suppression.
Les lignes de mots sont renormalisées sur les mots visibles : un poids affiché est une part de ce qui reste après retrait de [CLS] et [SEP]. Basculez pour voir la même ligne avant retrait.
Basculez entre les deux vues. Les barres ont la même forme — évidemment, renormaliser est une mise à l'échelle uniforme — mais une ligne décrit ce que le modèle a fait, l'autre ce qui restait après montage.
Mesuré sur 61 lignes ciblées, réparties sur neuf phrases :
| Part médiane retirée d'une ligne | 24 % |
| Lignes perdant plus de la moitié | 19 sur 61 |
| Pire cas | 95 % |
Un quart d'une ligne typique, disparu avant affichage. Rien à l'écran ne le disait.
Le code d'agrégation calculait cette quantité retirée depuis le jour où il avait été écrit. Il existait une variable removedMass, et un test unitaire vérifiant sa justesse.
Puis le worker la jetait et ne l'envoyait jamais à l'interface.
La machinerie d'honnêteté avait été construite, testée, puis débranchée. C'est pire que de ne pas l'avoir, car toutes les personnes concernées — moi compris — pouvaient montrer un test prouvant que le nombre était connu.
Connaître un nombre et l'afficher sont deux réussites distinctes, et seule la seconde atteint un lecteur.
Pas une réécriture. Une montée de version du protocole pour que la part retirée voyage avec chaque matrice, puis l'obligation pour l'interface de l'énoncer.
Trois changements, par ordre de difficulté :
Le nombre est énoncé. Chaque ligne ciblée indique désormais quelle part est allée vers [CLS]/[SEP], et au-delà de 50 % elle le dit en toutes lettres plutôt que sous forme d'un chiffre qu'on survole.
Les lignes de puits sont marquées et atténuées. La ponctuation absorbe des poids énormes dans la plupart des têtes — heads → . mesure 0,983 dans l'une d'elles — elle est donc exclue du choix du pic qui nomme une ligne. Elle reste affichée, classée, à sa valeur exacte. Elle n'a simplement plus le droit de définir le sujet de la ligne.
Le panneau explique son propre en-tête. Pour Water boils at 100°c., l'en-tête affichait 100°c 0,163 au-dessus d'une liste dont la première entrée était . 0,438. Les deux vrais. Rien n'expliquait ce désaccord ; désormais le panneau dit : cette tranche est nommée d'après le mot de contenu le plus fort, et voici le poids de ponctuation qui le dépasse.
Et le téléphone a tout reçu. Chaque nuance était en hidden md:block ou enfouie dans un panneau fermé — ce qui est à l'envers, puisque le visiteur mobile est justement celui qui ne peut pas ouvrir la matrice et vérifier lui-même.
J'ai essayé. C'est pire.
Un arc tracé vers [SEP] pointe vers un token que le lecteur n'a jamais tapé et ne peut pas interpréter. Il domine l'image, n'apprend rien sur sa phrase et fait paraître l'outil cassé. La vue renormalisée est réellement la plus utile : elle répond à « parmi les mots que j'ai écrits, où est allée l'attention ? », qui est la question posée.
Le défaut n'a jamais été la renormalisation. C'était de renormaliser en silence. Une part d'un sous-ensemble est parfaitement affichable, à condition de dire au lecteur de quel sous-ensemble il s'agit et quelle proportion de l'original manque.
Cette distinction — entre un nombre faux et un nombre vrai qui induit en erreur — est celle autour de laquelle tourne tout ce projet. Cinq défauts corrigés en une seule journée avaient tous cette forme : arithmétique correcte, présentation trompeuse.
Il existe une technique publiée qui prétend dissoudre entièrement ce problème, en mesurant ce qui circule réellement plutôt que ce qui est regardé. La partie 9 la teste.
Ensuite : la façon mathématiquement correcte de combiner les seize têtes, et pourquoi elle ne dit presque rien.
Plus à lire
La table d'embeddings pèse 31 254 528 octets. Une phrase de douze mots en utilise environ 20 Ko. HTTP Range fait que c'est la seule partie qui circule.
Chaque ligne de rollout se situe entre 0,935 et 0,971 d'entropie normalisée. C'est une distribution uniforme déguisée en classement, et c'était la vue par défaut.
L'int8 naïf plafonnait la parité d'attention à 2,97e-2 — trente fois pire que la barre. Où dépenser la précision : voilà toute l'ingénierie.