web-dev-qa-db-fra.com

Comment définir le taux d'apprentissage adaptatif pour GradientDescentOptimizer?

J'utilise TensorFlow pour former un réseau de neurones. Voici comment j'initialise la GradientDescentOptimizer:

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

mse        = tf.reduce_mean(tf.square(out - out_))
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)

La chose ici est que je ne sais pas comment définir une règle de mise à jour pour le taux d'apprentissage ou une valeur de déclin pour cela.

Comment utiliser un taux d'apprentissage adaptatif ici?

93
displayname

Tout d'abord, _tf.train.GradientDescentOptimizer_ est conçu pour utiliser un taux d'apprentissage constant pour toutes les variables dans toutes les étapes. TensorFlow fournit également des optimiseurs adaptatifs prêts à l'emploi, notamment le tf.train.AdagradOptimizer et le tf.train.AdamOptimizer , et ceux-ci peuvent être utilisés comme remplacements directs.

Toutefois, si vous souhaitez contrôler le taux d’apprentissage avec une descente de gradient d’une autre manière, vous pouvez tirer parti du fait que l’argument _learning_rate_ du constructeur tf.train.GradientDescentOptimizer peut être un objet Tensor. Cela vous permet de calculer une valeur différente pour le taux d'apprentissage à chaque étape, par exemple:

_learning_rate = tf.placeholder(tf.float32, shape=[])
# ...
train_step = tf.train.GradientDescentOptimizer(
    learning_rate=learning_rate).minimize(mse)

sess = tf.Session()

# Feed different values for learning rate to each training step.
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.01})
sess.run(train_step, feed_dict={learning_rate: 0.01})
_

Vous pouvez également créer un scalaire _tf.Variable_ contenant le taux d’apprentissage et l’affecter à chaque fois que vous souhaitez modifier le taux d’apprentissage.

186
mrry

Tensorflow permet d’appliquer automatiquement une décroissance exponentielle à un tenseur du taux d’apprentissage: tf.train.exponential_decay . Pour un exemple d'utilisation, voir cette ligne dans l'exemple de modèle de convolution MNIST . Utilisez ensuite la suggestion de @ mrry ci-dessus pour fournir cette variable en tant que paramètre learning_rate à l'optimiseur de votre choix.

L'extrait clé à regarder est:

_# Optimizer: set up a variable that's incremented once per batch and
# controls the learning rate decay.
batch = tf.Variable(0)

learning_rate = tf.train.exponential_decay(
  0.01,                # Base learning rate.
  batch * BATCH_SIZE,  # Current index into the dataset.
  train_size,          # Decay step.
  0.95,                # Decay rate.
  staircase=True)
# Use simple momentum for the optimization.
optimizer = tf.train.MomentumOptimizer(learning_rate,
                                     0.9).minimize(loss,
                                                   global_step=batch)
_

Notez le paramètre _global_step=batch_ à réduire. Cela indique à l'optimiseur d'incrémenter utilement le paramètre 'batch' pour vous chaque fois qu'il s'entraîne.

87
dga

L'algorithme de descente de gradient utilise le taux d'apprentissage constant que vous pouvez fournir en pendant l'initialisation . Vous pouvez passer différents taux d’apprentissage de la manière montrée par Mrry.

Mais au lieu de cela, vous pouvez également utiliser optimiseurs plus avancés qui ont un taux de convergence plus rapide et s’adapte à la situation.

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 d’amplifier la vitesse dans le bon sens et d’atténuer 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 ne fera qu'entraver 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 effectuons 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 la nécessité 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 d’apprendre.
  • AdaDelta résout le problème de la diminution monotone du taux d’apprentissage 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 diminution 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 taux d’apprentissage pour chacun des paramètres, il stocke également les changements d’élan pour chacun d’eux séparément.

    A quelques visualisations : enter image description hereenter image description here

81
Salvador Dali

De tensorflow documentation officielle

global_step = tf.Variable(0, trainable=False)
starter_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,
                                       100000, 0.96, staircase=True)

# Passing global_step to minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss..., global_step=global_step))
6
Prakash Vanapalli

Si vous souhaitez définir des vitesses d’apprentissage spécifiques pour des intervalles d’époques tels que 0 < a < b < c < .... Vous pouvez ensuite définir votre vitesse d’apprentissage en tant que tenseur conditionnel, conditionnel à l’étape globale, et l’envoyer normalement à l’optimiseur.

Vous pouvez y parvenir avec un tas d'instructions imbriquées tf.cond, mais il est plus facile de construire le tenseur récursivement:

def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
    assert len(reduction_steps) + 1 == len(learning_rates)
    if len(reduction_steps) == 1:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: learning_rates[1]
        )
    else:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: make_learning_rate_tensor(
                reduction_steps[1:],
                learning_rates[1:],
                global_step,)
            )

Ensuite, pour l'utiliser, vous devez savoir combien d'étapes de formation il y a dans une même époque, afin que nous puissions utiliser l'étape globale pour passer au bon moment, et enfin définir les époques et les vitesses d'apprentissage souhaitées. Donc, si je veux les taux d'apprentissage [0.1, 0.01, 0.001, 0.0001] pendant les intervalles de temps de [0, 19], [20, 59], [60, 99], [100, \infty] respectivement, je ferais:

global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_Epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_Epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)
0
Ben