Accélérez avec Newton et quasi-Newton
La descente de gradient n’utilise qu’une information : la pente. Elle ignore si le terrain est une cuvette étroite ou une large plaine, et c’est pour cela qu’elle zigzague dès que les lignes de niveau s’allongent. Notre randonneur ferait mieux s’il sentait aussi la courbure du sol : dans une cuvette bien arrondie, il pourrait deviner où se trouve le fond et y sauter directement.
C’est l’idée de la méthode de Newton. Elle converge en une poignée d’itérations là où le gradient en demande des centaines, mais elle coûte plus cher et peut s’égarer. Dans ce chapitre, vous allez la voir à l’œuvre sur la fonction de notre TP, comprendre ses limites, puis découvrir les méthodes de quasi-Newton, le compromis utilisé en pratique.
L’idée : sauter au fond d’un modèle quadratique
Section intitulée « L’idée : sauter au fond d’un modèle quadratique »Près du point courant , Taylor à l’ordre 2 approche par une quadratique :
Si la Hessienne est définie positive, ce modèle a un unique minimum, là où son gradient s’annule. La méthode de Newton saute directement à ce minimum :
- est le gradient au point courant ;
- est la Hessienne, et son inverse ;
- le déplacement s’appelle la direction de Newton.
En dimension 1, la formule devient . Vous reconnaissez peut-être la méthode de Newton pour résoudre une équation : c’est exactement elle, appliquée à l’équation . On trace la tangente au graphe de et l’on prend son intersection avec l’axe horizontal.
Comparez avec le gradient : Newton, c’est un gradient dont le pas est remplacé par l’inverse de la courbure. Là où la fonction est très courbée, il fait de petits pas ; là où elle est plate, de grands pas. Et comme il corrige chaque direction selon sa propre courbure, le conditionnement ne le gêne plus.
Newton en dimension 1 : notre TP
Section intitulée « Newton en dimension 1 : notre TP »En TP, nous avons appliqué Newton à , avec et , depuis trois points de départ : 0,8, 1 et 1,4. Avec les mêmes critères d’arrêt que pour le gradient (tolérance 0,025 sur , 20 itérations au plus), la sortie affichée pour le dernier départ, , donne un minimum en , avec . Si l’on rejoue le code du TP avec ces critères, Newton s’arrête après deux itérations seulement depuis 1,4 (et trois depuis 0,8 ou 1), là où le gradient à pas fixe 0,1 en enchaînait 18 pour arriver au même endroit.
Pour voir la vitesse de Newton, suivons l’erreur depuis , en continuant au-delà de la tolérance du TP () :
| Erreur | ||
|---|---|---|
| 0 | 1 | |
| 1 | 1,25 | |
| 2 | 1,206667 | |
| 3 | 1,205073 | |
| 4 | 1,205071 |
Le nombre de décimales exactes double à chaque itération. C’est la convergence quadratique : près de la solution, l’erreur vérifie pour une constante . En comparaison, le gradient a une convergence linéaire : l’erreur est multipliée par un facteur constant à chaque pas, et chaque décimale coûte le même nombre d’itérations.
Quand Newton part trop loin
Section intitulée « Quand Newton part trop loin »Ce bel ordre ne vaut que près de la solution. Partons de : la courbure y est minuscule, , alors que la pente est forte, . Le modèle quadratique est une parabole très évasée dont le fond est loin, et Newton y saute : . Loin de l’origine, et chaque pas de Newton ne réduit que d’un tiers : 38,9, puis 26,0, puis 17,3… Il faut une douzaine d’itérations pour revenir près de 1,2. Et depuis , c’est pire : , la formule divise par zéro et la méthode ne peut même pas démarrer.
Newton en dimension n
Section intitulée « Newton en dimension n »En dimension , on ne calcule jamais l’inverse de la Hessienne. On résout le système linéaire
puis on pose . Résoudre un système coûte moins cher et est numériquement plus stable qu’inverser une matrice.
Le revers de la médaille, c’est le coût. À chaque itération, il faut :
- calculer la Hessienne, soit dérivées secondes (environ grâce à la symétrie) ;
- résoudre un système , en opérations.
Pour , c’est instantané. Pour un réseau de neurones à paramètres, la Hessienne aurait coefficients : impossible même à stocker.
Les limites de Newton, et comment les contourner
Section intitulée « Les limites de Newton, et comment les contourner »Newton cherche un point où le gradient s’annule. Il ne sait pas faire la différence entre un minimum, un maximum et un col. Si la Hessienne n’est pas définie positive, la direction de Newton n’est pas forcément une direction de descente, et la méthode peut monter.
Deux remèdes classiques rendent la méthode robuste :
- Newton amorti (damped Newton) : on garde la direction de Newton mais l’on choisit le pas par une recherche linéaire d’Armijo (chapitre 6). Loin de la solution, on fait des pas raisonnables ; près d’elle, le pas 1 est accepté et l’on retrouve la convergence quadratique.
- Correction de la Hessienne : si elle n’est pas définie positive, on la remplace par avec assez grand. Quand est grand, on retombe sur un petit pas de gradient ; quand il est petit, sur Newton. C’est l’idée de la méthode de Levenberg-Marquardt, très utilisée pour les moindres carrés non linéaires.
Les méthodes de quasi-Newton
Section intitulée « Les méthodes de quasi-Newton »Peut-on avoir la vitesse de Newton sans payer la Hessienne ? Presque. Les méthodes de quasi-Newton construisent une approximation de la Hessienne (ou de son inverse) à partir des gradients déjà calculés, sans aucune dérivée seconde.
L’idée vient de la dimension 1 : la dérivée seconde est la variation de la dérivée, que l’on peut estimer entre deux itérées. En dimension , on note le déplacement et la variation du gradient. On impose à la nouvelle approximation de la Hessienne la condition de la sécante :
Autrement dit, doit expliquer la variation de gradient qu’on vient d’observer. Parmi toutes les matrices qui la vérifient, la méthode BFGS (Broyden, Fletcher, Goldfarb, Shanno) choisit la plus proche de la précédente, et met directement à jour l’approximation de l’inverse de la Hessienne :
La direction est alors : un simple produit matrice-vecteur, en , sans système à résoudre. Si est définie positive et (ce que garantit une bonne recherche linéaire), l’est aussi : les directions restent des directions de descente. La convergence est superlinéaire : plus rapide que linéaire, un peu moins que quadratique.
Pour les très grandes dimensions, L-BFGS (limited memory) ne stocke même pas la matrice : il garde seulement les derniers couples , avec de l’ordre de 5 à 20, et reconstruit le produit à la volée. C’est l’algorithme par défaut de nombreux solveurs, notamment pour la régression logistique dans scikit-learn.
En pratique, on n’implémente pas BFGS soi-même, on appelle SciPy :
import numpy as npfrom scipy.optimize import minimize
def rosenbrock(v): x, y = v return (1 - x) ** 2 + 100 * (y - x ** 2) ** 2
def grad_rosenbrock(v): x, y = v return np.array([-2 * (1 - x) - 400 * x * (y - x ** 2), 200 * (y - x ** 2)])
res = minimize(rosenbrock, x0=[-1.2, 1.0], jac=grad_rosenbrock, method="BFGS")print(res.x, res.nit) # un point très proche de (1, 1), en quelques dizaines d'itérationsPour choisir, retenez ce tableau :
| Gradient | Newton | Quasi-Newton (BFGS) | |
|---|---|---|---|
| Information utilisée | gradient | gradient et Hessienne | gradients successifs |
| Coût d’une itération | , ou pour L-BFGS | ||
| Vitesse près de la solution | linéaire, sensible au conditionnement | quadratique | superlinéaire |
| Robustesse loin de la solution | bonne avec un petit pas | faible sans amortissement | bonne avec recherche linéaire |
| Usage typique | très grandes dimensions, apprentissage profond | petites dimensions, haute précision | dimensions moyennes à grandes |
En résumé
Section intitulée « En résumé »- Newton minimise le modèle quadratique de Taylor : ; en dimension 1, .
- Près d’un minimum, sa convergence est quadratique ; sur une quadratique, il trouve le minimum en une itération.
- On résout le système sans inverser la Hessienne ; le coût est en par itération.
- Loin de la solution, Newton peut faire des sauts énormes, et il converge vers n’importe quel point critique, col compris ; on le stabilise par recherche linéaire ou en ajoutant à la Hessienne.
- Les méthodes de quasi-Newton (BFGS, L-BFGS) approchent la Hessienne grâce à la condition de la sécante : convergence superlinéaire sans dérivée seconde.
Exercices
Section intitulée « Exercices »Exercice · Trois itérations de Newton
facileAppliquez la méthode de Newton à depuis pendant trois itérations. Quel est le minimum exact ?
Voir la solution
On a et : est strictement convexe, et son minimum vérifie , soit .
La formule donne .
- ;
- ;
- .
Les erreurs valent environ 0,31, puis 0,043, puis 0,0009 : le nombre de décimales exactes double à peu près à chaque pas. L’itération suivante donne 0,693148, à près.
En code
import numpy as np
x = 0.0for k in range(1, 5): x = x - (np.exp(x) - 2) / np.exp(x) # x - f'(x) / f''(x) print(k, round(x, 6), f"erreur {abs(x - np.log(2)):.1e}")# 1 1.0 erreur 3.1e-01# 2 0.735759 erreur 4.3e-02# 3 0.694042 erreur 9.0e-04# 4 0.693148 erreur 4.0e-07x <- 0for (k in 1:4) { x <- x - (exp(x) - 2) / exp(x) # x - f'(x) / f''(x) cat(k, round(x, 6), "erreur", signif(abs(x - log(2)), 2), "\n")}# 1 1 erreur 0.31# 2 0.735759 erreur 0.043# 3 0.694042 erreur 9e-04# 4 0.693148 erreur 4e-07Exercice · Newton sur une quadratique
moyenAppliquez une itération de Newton à depuis l’origine. Comparez au minimum trouvé au chapitre 5, et expliquez.
Voir la solution
Le gradient vaut , soit à l’origine. La Hessienne est constante : . On résout : et , d’où , .
Le nouveau point est : c’est exactement le minimum trouvé au chapitre 5. Comme est quadratique, son développement de Taylor à l’ordre 2 est exact, et Newton, qui minimise ce développement, tombe sur le minimum en une itération, quel que soit le point de départ.
En code
import numpy as np
grad = lambda v: np.array([2 * v[0] + v[1] - 3, v[0] + 2 * v[1]])H = np.array([[2.0, 1.0], [1.0, 2.0]]) # Hessienne constante
for depart in ([0.0, 0.0], [10.0, -7.0]): x = np.array(depart) x = x + np.linalg.solve(H, -grad(x)) # une itération de Newton print(depart, "->", x, grad(x)) # toujours [ 2. -1.], gradient nulgrad <- function(v) c(2 * v[1] + v[2] - 3, v[1] + 2 * v[2])H <- rbind(c(2, 1), c(1, 2)) # Hessienne constante
for (depart in list(c(0, 0), c(10, -7))) { x <- depart + solve(H, -grad(depart)) # une itération de Newton cat(depart, "->", x, "; gradient", grad(x), "\n")}# 0 0 -> 2 -1 ; gradient 0 0# 10 -7 -> 2 -1 ; gradient 0 0 : le minimum en un pas, quel que soit le départExercice · Une direction qui monte
difficilePour l’altitude , au point :
- Calculez la direction de Newton et le produit scalaire . Est-ce une direction de descente ?
- Même question pour la direction du gradient.
- Proposez une modification de la Hessienne qui rende la direction de Newton descendante.
Voir la solution
- et . La direction de Newton vaut . Alors : c’est une direction de montée. Elle mène vers le col en .
- La direction du gradient est , et : elle descend (vers l’est, en direction de la vallée en ).
- On remplace la Hessienne par , avec pour la rendre définie positive. Par exemple, avec , on obtient et la direction , qui descend. Une matrice définie positive donne toujours une direction de descente, car dès que le gradient est non nul.
En code
import numpy as np
x = np.array([-0.9, 0.0])g = np.array([3 * x[0]**2 - 3, 2 * x[1]]) # (-0.57, 0)H = np.diag([6 * x[0], 2.0]) # diag(-5.4, 2)
h_newton = np.linalg.solve(H, -g)print(h_newton, g @ h_newton) # [-0.1056 0.] 0.0602 > 0 : montéeprint(-g, g @ -g) # [0.57 0.] -0.3249 < 0 : descente
h_corrige = np.linalg.solve(H + 6.4 * np.eye(2), -g) # λ = 6,4 > 5,4print(h_corrige, g @ h_corrige) # [0.57 0.] -0.3249 : descentex <- c(-0.9, 0)g <- c(3 * x[1]^2 - 3, 2 * x[2]) # (-0.57, 0)H <- diag(c(6 * x[1], 2)) # diag(-5.4, 2)
h_newton <- solve(H, -g)h_newton; sum(g * h_newton) # -0.1056 0 ; 0.0602 > 0 : montéesum(g * -g) # -0.3249 < 0 : le gradient descend
h_corrige <- solve(H + 6.4 * diag(2), -g) # λ = 6,4 > 5,4h_corrige; sum(g * h_corrige) # 0.57 0 ; -0.3249 : descente