Un interprète est assis dans la salle de réunion et traduit chaque mot. Mais voilà qu'il remarque que sa traduction pourrait être améliorée s'il apprenait de ses erreurs. Il commence à noter les phrases qui ont causé des incompréhensions et les corrige. Au bout d'une heure, sa traduction est plus précise et la réunion se déroule plus vite. C'est exactement le principe ici : un interpréteur Scheme, compilé une seule fois, peut exécuter n'importe quel programme qui lui est fourni comme donnée, tout en calculant des gradients pour améliorer ces programmes.
Auparavant, chaque modèle scientifique devait être réécrit manuellement sous une forme différenciable pour appliquer l'optimisation par gradient. C'est comme si, pour chaque nouveau texte, il fallait engager un nouvel interprète. Désormais, l'interprète lui-même devient capable d'apprendre : il ne se contente pas de traduire, il comprend aussi comment modifier le texte pour le rendre meilleur. Les auteurs de ce travail ont créé un compilateur qui traduit le code source Scheme en une représentation intermédiaire ComputeGraph, puis en modules PyTorch ou JAX. La particularité essentielle est que c'est l'interpréteur lui-même qui devient différenciable, et non les programmes individuels.
À l'intérieur de l'interpréteur, toutes les valeurs sont représentées par des vecteurs de dimension 14 : un vecteur one-hot de 10 dimensions pour le type et une charge utile de 4 dimensions. Le tas est implémenté comme un dictionnaire à écriture unique, ce qui préserve la correction des gradients. Pour les appels terminaux, on utilise un trampoline, c'est-à-dire une boucle qui remplace la récursion profonde et empêche la pile de croître. Grâce à cela, les gradients calculés via l'interpréteur compilé coïncident avec ceux d'une compilation directe à moins de 7×10⁻⁷ près sur la fonction de perte, pour 171 paires (programme, valeur initiale).
Sur des données réelles de dégradation de batteries, la recherche conjointe de structure et de paramètres a retrouvé la structure en coude de la dégradation à partir d'une initialisation lisse, et a amélioré l'extrapolation sur des données de test. Dans le problème de modélisation inverse d'El Niño, l'interpréteur différenciable a permis d'optimiser la vraisemblance du filtre de Kalman avec 611 paramètres, là où une recherche sans gradient échouait. Le traitement par lots a accéléré le débit jusqu'à 875 fois.
L'interprète ne se contente plus de traduire, il apprend de chaque mot. Il peut automatiquement calibrer les paramètres de modèles générés par des modèles de langage, dans des tâches scientifiques et d'ingénierie. C'est comme si l'interprète, recevant un brouillon de l'écrivain, le peaufinait lui-même sans qu'il soit nécessaire de tout réécrire. Pour revenir au début : un interprète qui apprend de chaque mot transforme une heure de réunion en quelques minutes, et rend la science plus rapide et plus précise.
L'interpréteur Scheme, écrit en Scheme lui-même, ne compte que 288 lignes de code. Il supporte pourtant les fermetures, la récursion, les listes et les appels terminaux, suffisamment pour être auto-applicable.
L'idée d'un programme capable de se modifier et de s'améliorer lui-même par gradients fait écho au concept de machines gödeliennes de Jürgen Schmidhuber, décrit dans ses travaux sur l'auto-amélioration universelle.