web-dev-qa-db-fra.com

Comment changer un taux d'apprentissage pour Adam dans TF2?

Comment changer le taux d'apprentissage de l'optimiseur Adam, tandis que l'apprentissage progresse dans TF2? Il y a des réponses flottantes, mais applicables à TF1, par exemple en utilisant feed_dict.

13
Slawek Smyl

Vous pouvez lire et affecter le taux d'apprentissage via un rappel . Vous pouvez donc utiliser quelque chose comme ceci:

class LearningRateReducerCb(tf.keras.callbacks.Callback):

  def on_Epoch_end(self, Epoch, logs={}):
    old_lr = self.model.optimizer.lr.read_value()
    new_lr = old_lr * 0.99
    print("\nEpoch: {}. Reducing Learning Rate from {} to {}".format(Epoch, old_lr, new_lr))
    self.model.optimizer.lr.assign(new_lr)

Qui, par exemple, en utilisant la démo mnist peut être appliqué comme suit:

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, callbacks=[LearningRateReducerCb()], epochs=5)

model.evaluate(x_test, y_test)

donner une sortie comme ceci:

Train on 60000 samples
Epoch 1/5
59744/60000 [============================>.] - ETA: 0s - loss: 0.2969 - accuracy: 0.9151
Epoch: 0. Reducing Learning Rate from 0.0010000000474974513 to 0.0009900000877678394
60000/60000 [==============================] - 6s 92us/sample - loss: 0.2965 - accuracy: 0.9152
Epoch 2/5
59488/60000 [============================>.] - ETA: 0s - loss: 0.1421 - accuracy: 0.9585
Epoch: 1. Reducing Learning Rate from 0.0009900000877678394 to 0.000980100128799677
60000/60000 [==============================] - 5s 91us/sample - loss: 0.1420 - accuracy: 0.9586
Epoch 3/5
59968/60000 [============================>.] - ETA: 0s - loss: 0.1056 - accuracy: 0.9684
Epoch: 2. Reducing Learning Rate from 0.000980100128799677 to 0.0009702991228550673
60000/60000 [==============================] - 5s 91us/sample - loss: 0.1056 - accuracy: 0.9684
Epoch 4/5
59520/60000 [============================>.] - ETA: 0s - loss: 0.0856 - accuracy: 0.9734
Epoch: 3. Reducing Learning Rate from 0.0009702991228550673 to 0.0009605961386114359
60000/60000 [==============================] - 5s 89us/sample - loss: 0.0857 - accuracy: 0.9733
Epoch 5/5
59712/60000 [============================>.] - ETA: 0s - loss: 0.0734 - accuracy: 0.9772
Epoch: 4. Reducing Learning Rate from 0.0009605961386114359 to 0.0009509901865385473
60000/60000 [==============================] - 5s 87us/sample - loss: 0.0733 - accuracy: 0.9772
10000/10000 [==============================] - 0s 43us/sample - loss: 0.0768 - accuracy: 0.9762
[0.07680597708942369, 0.9762]
5
Stewart_R

Si vous souhaitez utiliser le contrôle de bas niveau et non la fonctionnalité fit avec rappels, consultez tf.optimizers.schedules . Voici un exemple de code:

train_steps = 25000
lr_fn = tf.optimizers.schedules.PolynomialDecay(1e-3, train_steps, 1e-5, 2)
opt = tf.optimizers.Adam(lr_fn)

Cela décrivait le taux d'apprentissage de 1E-3 à 1E-5 sur 25 000 étapes avec une décomposition polynomiale Power-2.

Noter:

  • Cela ne "stocke pas vraiment" un taux d'apprentissage comme dans l'autre réponse, mais le taux d'apprentissage est maintenant une fonction qui sera appelée à chaque fois qu'il est nécessaire de calculer le taux d'apprentissage actuel.
  • Optimizer Les instances ont un compteur de pas interne qui comptera par une chaque fois apply_gradients est appelé (autant que je puisse dire ...). Cela permet à cette procédure de fonctionner correctement lorsque vous l'utilisez dans un contexte de bas niveau (généralement avec tf.GradientTape)
  • Malheureusement, cette fonctionnalité n'est pas bien documentée (Docs disent simplement que l'argument du tarif d'apprentissage doit être un flotteur ou un tenseur ...) mais cela fonctionne. Vous pouvez également écrire vos propres horaires de décomposition. Je pense qu'ils doivent simplement avoir besoin d'être des fonctions qui prennent dans certains "State" actuels de l'optimiseur (probablement du nombre d'étapes de formation) et de renvoyer un flotteur à utiliser comme taux d'apprentissage.
3
xdurch0

Si vous utilisez une boucle de formation personnalisée (au lieu de keras.fit()), vous pouvez simplement faire:

new_learning_rate = 0.01 
my_optimizer.lr.assign(new_learning_rate)
3
Ali Salehi

Vous avez 3 solutions:

Voici un exemple de - ce tutoriel :

class CustomSchedule(tf.keras.optimizers.schedules.LearningRateSchedule):
    def __init__(self, d_model, warmup_steps=4000):
        super(CustomSchedule, self).__init__()

        self.d_model = d_model
        self.d_model = tf.cast(self.d_model, tf.float32)

        self.warmup_steps = warmup_steps

    def __call__(self, step):
        arg1 = tf.math.rsqrt(step)
        arg2 = step * (self.warmup_steps ** -1.5)

        return tf.math.rsqrt(self.d_model) * tf.math.minimum(arg1, arg2)

Et vous le transmettez à votre optimiseur:

learning_rate = CustomSchedule(d_model)

optimizer = tf.keras.optimizers.Adam(learning_rate, beta_1=0.9, beta_2=0.98, 
                                     epsilon=1e-9)

De cette façon, la tranche de douane fera partie de votre graphique et il mettra à jour le taux d'apprentissage pendant la formation de votre modèle.

0
Begoodpy