Qu’est-ce que la différentiation automatique?

Les modèles mathématiques de la physique regorgent de gradients, divergences, laplaciens, rotationnels, qui sont des dérivées en espace. On y trouve aussi des dérivées en temps pour les problèmes instationnaires. La dérivation est omniprésente.

Ce dont nous allons parler maintenant est plus général et vise jusqu’à la dérivation des modèles eux-mêmes par rapport à des variables diverses.

Motivation

Une telle dérivation intervient dès l’établissement des équations lorsque celles-ci dérivent d’un potentiel, ou bien pour leur résolution basée sur les informations données par le jacobien: le modèle est linéarisé.

Au-delà de la résolution de l’équation, l’optimisation des paramètres en vue d’un critère sur la solution tirera profit de la connaissance des dérivées de celle-ci par rapport à ceux-là, appelés encore sensibilité de la solution par rapport aux paramètres.

Entrons dans les détails bien connus des spécialistes de l’optimisation. Pour l’optimisation d’ordre 1, on observe que seule la variation efficace vis-à-vis du critère compte, c’est-à-dire la contraction de la variation de la solution avec le gradient du critère par rapport à la solution. Mais la variation de la solution résulte de la résolution d’un système linéaire que l’on peut choisir de transposer mathématiquement sur le gradient du critère. C’est la méthode adjointe, plus performante dès que le nombre de critères à optimiser est inférieur au nombre de paramètres de dérivation… En optimisation d’ordre supérieur, la combinaison de l’adjoint et des sensibilités sera utile.

Des méthodes très différentes

Qu’il s’agisse de variables inconnues ou de données, une fois discrétisées, le problème consiste à dériver une formule mathématique par rapport à une liste de ses entrées de calcul. Partant d’un code de calcul produisant le résultat de la formule mathématique à dériver, il existe trois méthodes pour développer le code fournissant la dérivée.

1. Différence finie

C’est la plus simple des méthodes: elle consiste à réutiliser le code original en faisant varier légèrement le paramètre d’entrée considéré et à faire la différence entre les deux résultats, que l’on divise par l’écart de paramètre. Avec un deuxième calcul pris en une valeur avec l’écart opposé, on obtient un résultat précis non plus au premier ordre mais au second.

Hélas les mathématiques sont contredites par l’informatique dont les arrondis vont empêcher les différences de se montrer précises, car les décimales en jeu seront de plus en plus faibles mais toujours relatives à la même valeur centrale. La précision est donc nécessairement limitée. De plus, le choix de l’écart -le fameux epsilon- pourra parfois n’être jamais satisfaisant si la quantité à dériver est une somme dont les termes sont d’ordre de grandeur différent sans relation avec l’ordre de grandeur de leurs variations… Le petit terme de variation importante sera écrasé et la dérivée perdra sa pertinence.

La méthode semi-analytique

Lorsque la solution provient de la résolution d’un système linéaire, plutôt que de faire la différence entre les solutions, il est préférable de la faire sur les seconds membres et de résoudre le système correspondant. C’est plus rapide et plus performant. Il faut bien sûr soit avoir une matrice constante soit être arrivé à convergence dans le cas linéarisé d’un algorithme de Newton. Voilà ce que dit l’analyse: on peut reporter la dérivation sur le second membre. Si celui-ci est calculé par différence finie, la méthode est dite semi-analytique.

Encore faut-il que le code ne soit plus tout-à-fait une boîte noire: il faut accéder au résultat du second membre avant la résolution du système linéaire. On reste donc à haut-niveau. La méthode de calcul de sensibilité dite semi-analytique est proposée par certains éditeurs.

2. La différentiation de code ligne-à-ligne (algorithmique)

C’est théoriquement le plus simple d’usage, grâce aux outils de différentiation automatique de code: on fournit le code, dont on précise la sortie et l’entrée, et l’outil génère le code calculant la dérivée. Pour cela, ligne après ligne, l’outil écrit le code contenant valeur et dérivée – car on sait dériver les fonctions de base – par chaînage direct ou inverse (adjoint). D’abord réservé au Fortran pour son absence de pointeurs, la méthode a été étendue au C++ par d’autres outils qui ont tiré profit de la surcharge d’opérateurs du langage pour minimiser la ré-ingénierie du code original. Les opérations sont en effet surchargées pour produire valeur et chaînage de dérivée au lieu de la valeur seule.

La méthode de différentiation algorithmique a tout son intérêt dans le cas de codes hérités complexes car, s’appuyant sur les mêmes calculs, elle évite le débogage d’un code nouveau. Elle demande néanmoins une assistance humaine experte pour être opérationnelle et efficace.

Le principe de la méthode semi-analytique doit absolument être employé pour éviter la dérivation ligne-à-ligne de la résolution du système linéaire. Voilà un exemple d’assistance humaine indispensable.

3. Dérivation symbolique de la formule

Dans l’idéal, on voudrait dériver symboliquement la formule et coder son calcul. Le faire à la main conduit à s’octroyer un temps de développement qu’on s’interdisait, tandis que passer par un logiciel de calcul formel a quelques inconvénients majeurs.

  • D’une part, il est difficile d’exprimer la formule quand elle s’appuie sur des concepts complexes comme les éléments finis et les maillages.
  • D’autre part, le résultat développé perd la structure tensorielle dont elle est issue et ne donne pas les performances optimales. L’optimisation de la génération de code par ces outils repose en effet sur l’identification de la répétition d’opérations de base comme les multiplications et les sommes de variables scalaires, alors qu’il y a mieux à faire, algébriquement parlant.

Selon les auteurs de la journée Algorithmic Differentiation Workshop organisée par le Groupe de Recherche GDR-Calcul du CNRS le 24 janvier 2019 à Paris, cela peut conduire à une explosion de la complexité des expressions.

C’est donc un défi…