Comportement étrange avec Adam optimizer lors d'un entraînement trop long

11

J'essaie de former un seul perceptron (1000 unités d'entrée, 1 sortie, pas de couches cachées) sur 64 points de données générés de manière aléatoire. J'utilise Pytorch en utilisant l'optimiseur Adam:

import torch
from torch.autograd import Variable

torch.manual_seed(545345)
N, D_in, D_out = 64, 1000, 1

x = Variable(torch.randn(N, D_in))
y = Variable(torch.randn(N, D_out))

model = torch.nn.Linear(D_in, D_out)
loss_fn = torch.nn.MSELoss(size_average=False)

optimizer = torch.optim.Adam(model.parameters())
for t in xrange(5000):
  y_pred = model(x)
  loss = loss_fn(y_pred, y)

  print(t, loss.data[0])

  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

Initialement, la perte diminue rapidement, comme prévu:

(0, 91.74887084960938)
(1, 76.85824584960938)
(2, 63.434078216552734)
(3, 51.46927261352539)
(4, 40.942893981933594)
(5, 31.819372177124023)

Environ 300 itérations, l'erreur atteint près de zéro:

(300, 2.1734419819452455e-12)
(301, 1.90354676465887e-12)
(302, 2.3347573874232808e-12)

Cela continue pendant quelques milliers d'itérations. Cependant, après un entraînement trop long, l'erreur recommence à augmenter:

(4997, 0.002102422062307596)
(4998, 0.0020302983466535807)
(4999, 0.0017039275262504816)

Pourquoi cela arrive-t-il?

Bai Li
la source
Je ne pense pas que le surapprentissage l'explique - la perte d'entraînement augmente, pas la perte de validation. Par exemple, cela ne se produit pas lors de l'utilisation de SGD, uniquement avec Adam.
Bai Li
Le modèle a 1000 paramètres et il n'y a qu'un seul point de données, donc le modèle doit correspondre exactement aux données et la perte doit être nulle.
Bai Li
Oh désolé, tu as raison. Il y a 64 points de données.
Bai Li
Il y a 64 points de données (c'est-à-dire des contraintes) et 1 000 paramètres, il est donc possible de trouver des choix pour les paramètres afin que l'erreur soit nulle (et c'est facile à faire analytiquement). Ma question est pourquoi Adam ne trouve-t-il pas cela.
Bai Li
Continuons cette discussion dans le chat .
Bai Li

Réponses:

19

Cette petite instabilité à la fin de la convergence est une caractéristique d'Adam (et RMSProp) en raison de la façon dont il estime les amplitudes moyennes du gradient sur les étapes récentes et les divise par elles.

dix-dixdix-5

Cela rend en fait Adam moins stable et pire pour votre problème qu'une descente de gradient plus basique, en supposant que vous vouliez obtenir une perte aussi proche de zéro numériquement que les calculs le permettent.

Dans la pratique sur les problèmes d'apprentissage profond, vous ne vous approchez pas de la convergence (et pour certaines techniques de régularisation telles que l'arrêt précoce, vous ne le souhaitez pas de toute façon), il n'est donc généralement pas une préoccupation pratique sur les types de problèmes Adam a été conçu pour.

Vous pouvez réellement voir cela se produire pour RMSProp dans une comparaison de différents optimiseurs (RMSProp est la ligne noire - regardez les toutes dernières étapes juste au moment où il atteint la cible):

entrez la description de l'image ici

Vous pouvez rendre Adam plus stable et capable de se rapprocher de la véritable convergence en réduisant le taux d'apprentissage. Par exemple

optimizer = torch.optim.Adam(model.parameters(), lr=1e-5)

lr=1e-5dix-7

Neil Slater
la source
Ceci est une visualisation spectaculaire, Neil. Quelles sont les dimensions réelles? Que représentent x et y? Les images ont-elles des époques delta t ou n par image? Je suppose que l'étoile est l'optimum global dans une représentation topographique de la disparité (erreur) par rapport à deux paramètres sélectionnés. Ma supposition est-elle correcte?
Douglas Daseeco
Ce n'est pas ma visualisation, vous la trouverez dans de nombreux endroits. Les dimensions sont des unités arbitraires de paramètres d'entrée pour une fonction de test, et le graphique montre les courbes de niveau de cette fonction (encore une fois en unités arbitraires, vraisemblablement mises à l'échelle pour que NN fonctionne correctement). Chaque cadre est une étape de mise à jour du poids. C'est probablement équivalent à une mise à jour de mini-batch, et en raison du comportement de SGD, je m'attends à ce qu'elle soit en fait résolue exactement en utilisant le vrai gradient de la fonction de test - c'est-à-dire qu'il n'y a pas de jeu de données ou d'échantillonnage.
Neil Slater
1

La raison est exactement celle mentionnée dans l'autre réponse avec une excellente suggestion d'utiliser un taux d'apprentissage plus petit pour éviter ce problème autour des petits gradients.

Je peux penser à quelques approches:

  1. Vous pouvez découper les dégradés avec une limite supérieure / inférieure, mais cela ne garantit pas la convergence et peut entraîner un gel de la formation en étant piégé dans certains minima locaux et ne jamais en sortir.

  2. Entraînez-vous avec une taille de lot plus élevée, plus d'époques et avec un taux d'apprentissage pourri. Maintenant, je n'ai aucune preuve pratique que l'augmentation de la taille d'un lot entraîne de meilleurs dégradés, mais d'après ce que j'avais observé en rencontrant des problèmes similaires au vôtre, cela a presque toujours aidé.

Je suis sûr qu'il existe d'autres méthodes (comme le taux d'apprentissage cyclique, etc.) qui essaient de trouver un taux d'apprentissage optimal basé sur des statistiques.

Sanjay Krishna
la source