web-dev-qa-db-fra.com

Gradient Descent vs Adagrad vs Momentum dans TensorFlow

J'étudie TensorFlow et comment l'utiliser, même si je ne suis pas un expert des réseaux de neurones et de l'apprentissage en profondeur (juste les bases).

Après des tutoriels, je ne comprends pas les différences réelles et pratiques entre les trois optimiseurs pour la perte. Je regarde le API et je comprends les principes, mais mes questions sont les suivantes:

1. Quand est-il préférable d'utiliser l'un au lieu des autres?

2. Y a-t-il des différences importantes à connaître?

61
Kyrol

Voici une brève explication basée sur ma compréhension:

  • momentum aide SGD pour naviguer dans les directions appropriées et atténuer les oscillations non pertinentes. Il ajoute simplement une fraction de la direction de l'étape précédente à une étape en cours. Cela permet une amplification de la vitesse dans le bon sens et atténue les oscillations dans le mauvais sens. Cette fraction est généralement dans la gamme (0, 1). Il est également judicieux d'utiliser l'élan adaptatif. Au début de l'apprentissage, un grand élan entravera votre progression. Il est donc logique d'utiliser quelque chose comme 0,01 et une fois que tous les gradients élevés ont disparu, vous pouvez utiliser un plus grand élan. Il y a un problème avec l'élan: lorsque nous sommes très près du but, notre élan est dans la plupart des cas très élevé et il ne sait pas qu'il devrait ralentir. Cela peut le faire rater ou osciller autour des minima
  • Le gradient accéléré de Nesterov résout ce problème en commençant à ralentir plus tôt. Dans l’élan, nous calculons d’abord le gradient puis faisons un saut dans cette direction, amplifié par l’élan que nous avions précédemment. NAG fait la même chose mais dans un autre ordre: au début, nous faisons un grand saut en fonction de nos informations stockées, puis nous calculons la pente et faisons une petite correction. Ce changement apparemment non pertinent donne des améliorations pratiques significatives.
  • AdaGrad ou gradient adaptatif permet au taux d’apprentissage de s’adapter en fonction de paramètres. Il effectue des mises à jour plus importantes pour les paramètres peu fréquents et des mises à jour plus petites pour les paramètres fréquents. Pour cette raison, il est bien adapté aux données éparses (PNL ou reconnaissance d’image). Un autre avantage est que cela élimine fondamentalement le besoin d'ajuster le taux d'apprentissage. Chaque paramètre a son propre taux d’apprentissage et, en raison des particularités de l’algorithme, le taux d’apprentissage décroît de façon monotone. Cela pose le plus gros problème: à un moment donné, le taux d’apprentissage est si faible que le système arrête l’apprentissage.
  • AdaDelta résout le problème du taux d’apprentissage décroissant de façon monotone dans AdaGrad. Dans AdaGrad, le taux d’apprentissage a été calculé approximativement comme un divisé par la somme des racines carrées. A chaque étape, vous ajoutez une autre racine carrée à la somme, ce qui entraîne une augmentation constante du dénominateur. Dans AdaDelta, au lieu de faire la somme de toutes les racines carrées antérieures, il utilise une fenêtre glissante qui permet à la somme de diminuer. RMSprop est très similaire à AdaDelta
  • Adam ou dynamique adaptative est un algorithme similaire à AdaDelta. Mais en plus de stocker les vitesses d'apprentissage pour chacun des paramètres, il stocke également les changements d'élan pour chacun d'eux séparément.

    A quelques visualisationsenter image description hereenter image description here

Je dirais que SGD, Momentum et Nesterov sont inférieurs aux 3 derniers.

176
Salvador Dali

La réponse de Salvador Dali explique déjà les différences entre certaines méthodes populaires (par exemple, les optimiseurs), mais je voudrais essayer de les développer davantage.
(Notez que nos réponses ne concordent pas sur certains points, en particulier en ce qui concerne ADAGRAD.)

Momentum classique (CM) vs gradient accéléré de Nesterov (NAG)

(Principalement basé sur la section 2 du document Sur l’importance de l’initialisation et de l’élan dans l’apprentissage en profondeur .)

Chaque étape de CM et de NAG est en réalité composée de deux sous-étapes:

  • Une sous-étape d'élan - Il s'agit simplement d'une fraction (généralement comprise dans l'intervalle [0.9,1)) De la dernière étape.
  • Une sous-étape dépendante du gradient - C’est comme l’étape habituelle de SGD - c’est le produit du taux d’apprentissage et du vecteur opposé au gradient, tandis que le gradient est calculé à partir du début de cette sous-étape.

CM prend d'abord la sous-étape de gradient, tandis que NAG prend la sous-étape d'élan en premier.

Voici une démonstration de ne réponse sur l'intuition pour CM et NAG :

CM vs NAG example

Donc, NAG semble être meilleur (au moins dans l'image), mais pourquoi?

La chose importante à noter est que peu importe la date de la sous-étape de la dynamique, ce serait la même chose dans les deux cas. Par conséquent, nous pourrions aussi bien nous comporter si la sous-étape d'élan a déjà été franchie.

La question est donc la suivante: en supposant que la sous-étape de gradient soit prise après la sous-étape d'élan, devrions-nous calculer la sous-étape de gradient comme si elle commençait à la position avant ou après la sous-étape d'élan?

"Après" semble être la bonne réponse car, généralement, le gradient à un certain point θ Vous indique approximativement la direction allant de θ À un minimum (avec la magnitude relativement correcte), tandis que le Un gradient à un autre point est moins susceptible de vous orienter dans la direction allant de θ à un minimum (avec l'ampleur relativement correcte).

Voici une démonstration (du gif ci-dessous):

CM vs NAG in a specific moment in the awesome gif

  • Le minimum correspond à l'étoile et les courbes sont courbes de nivea . (Pour une explication sur les courbes de niveau et sur leur position perpendiculaire au dégradé, voir vidéos 1 et 2 par le légendaire Blue1Brown .)
  • La (longue) flèche pourpre est la sous-étape de l’élan.
  • La flèche rouge transparente est la sous-étape du dégradé si elle commence avant la sous-étape de la quantité de mouvement.
  • La flèche noire est la sous-étape du dégradé si elle commence après la sous-étape de la quantité de mouvement.
  • CM se retrouverait dans la cible de la flèche rouge foncé.
  • NAG se retrouverait dans la cible de la flèche noire.

Notez que cet argument pour lequel NAG est meilleur est indépendant du fait que l'algorithme soit proche du minimum.
En général, NAG et CM ont souvent le problème d’accumuler plus d’élan que ce qui est bon pour eux. Ainsi, chaque fois qu’ils doivent changer de direction, ils ont un "temps de réponse" embarrassant. L'avantage de NAG sur CM que nous avons expliqué n'empêche pas le problème, mais rend seulement le "temps de réponse" de NAG moins gênant (mais gênant tout de même).

Ce problème de "temps de réponse" est magnifiquement démontré dans le gif par Alec Radford (apparu dans réponse de Salvador Dali ):
An example of the embarrassing response time of both momentum methods

ADAGRAD

(Principalement basé sur la section 2.2.2 dans ADADELTA: une méthode du taux d'apprentissage adaptatif (le document ADADELTA original), car je le trouve beaucoup plus accessible que Méthodes adaptatives de substitution pour l'apprentissage en ligne et stochastique Optimisation (le document original ADAGRAD).)

Dans SGD , l'étape est donnée par - learning_rate * gradient, Tandis que learning_rate Est un hyperparamètre.
ADAGRAD possède également un hyperparamètre learning_rate, Mais le taux d'apprentissage réel de chaque composant du dégradé est calculé individuellement.
La i - ème composante de la t - ème étape est donnée par:

              learning_rate 
- --------------------------------------- * gradient_i_t
  norm((gradient_i_1, ..., gradient_i_t))

tandis que:

  • gradient_i_k Est le i - ème composant du dégradé de la k - ème étape
  • (gradient_i_1, ..., gradient_i_t) Est un vecteur avec des composants t. Ce n’est pas intuitif (du moins pour moi) que la construction d’un tel vecteur ait un sens, mais c’est ce que fait l’algorithme (conceptuellement).
  • norm(vector) est la norme norme euclidienne (alias l2) de vector, qui est notre notion intuitive de longueur de vector .
  • De manière confuse, dans ADAGRAD (ainsi que dans d’autres méthodes), l’expression multipliée par gradient_i_t (Dans ce cas, learning_rate / norm(...)) est souvent appelée "taux d’apprentissage" (en fait, Je l'ai appelé "le taux d'apprentissage réel" dans le paragraphe précédent). J'imagine que c'est parce que dans SGD l'hyperparamètre learning_rate Et cette expression sont identiques.
  • Dans une implémentation réelle, une constante serait ajoutée au dénominateur pour éviter une division par zéro.

Par exemple. si:

  • Le i - ème composant du dégradé de la première étape est 1.15
  • Le i - ème composant du dégradé de la deuxième étape est 1.35
  • Le i - ème composant du dégradé de la troisième étape est 0.9

Alors la norme de (1.15, 1.35, 0.9) Est la longueur de la ligne jaune, qui est:
sqrt(1.15^2 + 1.35^2 + 0.9^2) = 1.989.
Et le composant i de la troisième étape est: - learning_rate / 1.989 * 0.9

l2 norm example

Notez deux choses à propos du i - ème composant de l’étape:

  1. C'est proportionnel à learning_rate.
  2. Dans les calculs, la norme augmente et le taux d’apprentissage diminue.

Cela signifie qu'ADAGRAD est sensible au choix de l'hyperparamètre learning_rate.
En outre, il se peut qu'après un certain temps, les étapes deviennent si petites que l'ADAGRAD reste pratiquement bloqué.

ADADELTA et RMSProp

Du papier ADADELTA :

L'idée présentée dans ce document a été dérivée d'ADAGRAD afin de remédier aux deux principaux inconvénients de la méthode: 1) la décroissance continue des taux d'apprentissage tout au long de la formation, et 2) la nécessité d'un taux d'apprentissage global sélectionné manuellement.

Le document explique ensuite une amélioration destinée à remédier au premier inconvénient:

Au lieu d’accumuler la somme des gradients carrés sur tous les temps, nous avons limité la fenêtre des gradients antérieurs accumulés à une taille fixe w [...]. Cela garantit que l'apprentissage continue de progresser même après de nombreuses itérations de mises à jour.
La mémorisation de w des gradients carrés précédents étant inefficace, nos méthodes implémentent cette accumulation comme une moyenne en décroissance exponentielle des gradients carrés.

Par "moyenne décroissante exponentielle des gradients carrés", le papier signifie que pour chaque i, nous calculons une moyenne pondérée de toutes les composantes i carrées de tous les gradients calculés.
Le poids de chaque élément i au carré est supérieur au poids du composant i au carré de l'étape précédente.

Il s’agit d’une approximation d’une fenêtre de taille w car les poids des étapes précédentes sont très faibles.

(Quand je pense à une moyenne en décroissance exponentielle, j'aime visualiser un sentier de la comète , qui devient de plus en plus sombre à mesure qu'il s'éloigne de la comète:

a comet's trail as an intuition for a moving average )

Si vous modifiez uniquement ADAGRAD, vous obtiendrez RMSProp, une méthode proposée par Geoff Hinton dans Lecture 6e de sa classe Coursera .

Ainsi, dans RMSProp, la i - ème composante de la t - ème étape est donnée par:

                   learning_rate
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon)

tandis que:

  • epsilon est un hyperparamètre qui empêche une division par zéro.
  • exp_decay_avg_of_squared_grads_i Est une moyenne décroissante de façon exponentielle des composantes au carré i de la totalité des gradients calculés (y compris gradient_i_t).

Mais comme mentionné ci-dessus, ADADELTA vise également à se débarrasser de l'hyperparamètre learning_rate, Il doit donc y avoir plus de choses à l'intérieur.

Dans ADADELTA, le i - ème composant de la t - ème étape est donné par:

  sqrt(exp_decay_avg_of_squared_steps_i + epsilon)
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon) 

tandis que exp_decay_avg_of_squared_steps_i est une moyenne en décroissance exponentielle des composantes au carré i de la totalité des étapes calculées (jusqu’à la t-1 - ème étape).
sqrt(exp_decay_avg_of_squared_steps_i + epsilon) est un peu similaire à la quantité de mouvement et, selon le document , il "agit comme un terme d'accélération". (Le papier donne également une autre raison pour laquelle il a été ajouté, mais ma réponse est déjà trop longue, alors si vous êtes curieux, consultez la section 3.2.)

Adam

(Principalement basé sur Adam: une méthode d'optimisation stochastique , le document d'Adam original.)

Adam est l'abréviation de Adaptive Moment Estimation (voir cette réponse pour une explication sur le nom).
La i - ème composante de la t - ème étape est donnée par:

                   learning_rate
- ------------------------------------------------ * exp_decay_avg_of_grads_i
  sqrt(exp_decay_avg_of_squared_grads_i) + epsilon

tandis que:

  • exp_decay_avg_of_grads_i Est une moyenne en décroissance exponentielle des i - ème éléments de tous les gradients calculés (y compris gradient_i_t).
  • En fait, exp_decay_avg_of_grads_i Et exp_decay_avg_of_squared_grads_i Sont également corrigés pour tenir compte d'un biais en faveur de 0 (Pour plus d'informations à ce sujet, voir la section 3 dans l'article , et aussi ne réponse dans stats.stackexchange ).

Notez que Adam utilise une moyenne décroissante de façon exponentielle des i - èmes composantes des gradients où la plupart des méthodes SGD utilisent la méthode i -ème composant du dégradé actuel. Cela entraîne Adam à se comporter comme "une balle lourde avec friction", comme expliqué dans l'article Les GAN formés par une règle de mise à jour à deux échelles de temps convergent vers un équilibre de Nash local .
Voir cette réponse pour en savoir plus sur la façon dont le comportement semblable au momentum d'Adam est différent du comportement habituel semblable au momentum.

11
Oren Milman

Résumons-nous à une question simple:

Quel optimiseur me donnerait le meilleur résultat/précision?

Il n'y a pas de solution miracle. Certains optimiseurs pour votre tâche fonctionneraient probablement mieux que les autres. Il n’ya aucun moyen de le savoir à l’avance, vous devez en essayer quelques-uns pour trouver le meilleur. La bonne nouvelle est que les résultats de différents optimiseurs seraient probablement proches les uns des autres. Vous devez cependant trouver les meilleurs hyperparamètres pour chaque optimiseur que vous choisissez.

Quel optimiseur dois-je utiliser maintenant?

Peut-être, prenez AdamOptimizer et exécutez-le pour learning_rate 0.001 et 0.0001. Si vous voulez de meilleurs résultats, essayez de courir pour d’autres vitesses d’apprentissage. Ou essayez d’autres optimiseurs et réglez leurs hyperparamètres.

Longue histoire

Il y a quelques aspects à considérer lors du choix de votre optimiseur:

  • Facile d'utilisation (c'est-à-dire à quelle vitesse vous pouvez trouver des paramètres qui fonctionnent pour vous);
  • Vitesse de convergence (de base comme SGD ou plus rapide que tout autre);
  • Empreinte mémoire (généralement entre 0 et x2 tailles de votre modèle);
  • Relation avec d'autres parties du processus de formation.

Plain SGD est le strict minimum possible: il multiplie simplement les gradients par le taux d'apprentissage et ajoute le résultat aux poids. SGD a un certain nombre de belles qualités: il n'a qu'un seul hyperparamètre; il n'a pas besoin de mémoire supplémentaire; cela a un effet minimal sur les autres parties de la formation. Il présente également deux inconvénients: il peut être trop sensible au choix du taux d’apprentissage et la formation peut prendre plus de temps que d’autres méthodes.

À partir de ces inconvénients simples de SGD, nous pouvons voir quelles sont les règles de mise à jour les plus compliquées (optimiseurs): nous sacrifions une partie de notre mémoire pour obtenir une formation plus rapide et, éventuellement, simplifier le choix des hyperparamètres.

surcharge de mémoire est généralement non significatif et peut être ignoré. Sauf si le modèle est extrêmement volumineux, si vous vous entraînez sur GTX760 ou si vous vous battez pour le leadership d'ImageNet. Des méthodes plus simples comme le momentum ou le gradient accéléré de Nesterov nécessitent 1,0 ou moins de la taille du modèle (taille des hyperparamètres du modèle). Les méthodes de second ordre (Adam, peut nécessiter deux fois plus de mémoire et de calcul.

Vitesse de convergence - sage presque tout est meilleur que SGD et tout le reste est difficile à comparer. AdamOptimizer peut très bien commencer l’entraînement presque immédiatement, sans échauffement.

Je considère que facile à utiliser est le plus important dans le choix d'un optimiseur. Différents optimiseurs ont un nombre différent d'hyperparamètres et ont une sensibilité différente. Je considère Adam comme le plus simple des plus facilement disponibles. Vous devez généralement vérifier 2-4 taux d’apprentissage entre 0.001 et 0.0001 pour savoir si le modèle converge bien. Pour comparer SGD (et élan), j’essaie généralement de [0.1, 0.01, ... 10e-5]. Adam a 2 autres hyperparamètres qui doivent rarement être changés.

Relation entre l'optimiseur et d'autres parties de la formation. Le réglage hyperparamètre implique généralement la sélection de {learning_rate, weight_decay, batch_size, droupout_rate} simultanément. Tous sont interdépendants et chacun peut être considéré comme une forme de régularisation du modèle. Par exemple, il faut faire très attention si weight_decay ou L2-norm est utilisé et éventuellement choisir AdamWOptimizer au lieu de AdamOptimizer.

2
y.selivonchyk