web-dev-qa-db-fra.com

Comment mettre à jour les poids manuellement avec Keras

J'utilise Keras pour construire un LSTM et le régler en faisant une descente de gradient avec une fonction de coût externe. Ainsi, les poids sont mis à jour avec:

weights := weights + alpha* gradient(cost)

Je sais que je peux obtenir les poids avec keras.getweights(), mais comment puis-je faire la descente du gradient et mettre à jour tous les poids et mettre à jour les poids en conséquence. J'essaie d'utiliser initializer, mais je ne l'ai toujours pas compris. Je n'ai trouvé que du code associé avec tensorflow mais je ne sais pas comment le convertir en Keras.

Toute aide, indice ou conseil sera apprécié!

10
beepretty

keras.layer.set_weights() est ce que vous recherchez:

import numpy as np
from keras.layers import Dense
from keras.models import Sequential

model = Sequential()
model.add(Dense(10, activation='relu', input_shape=(10,)))
model.add(Dense(5, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='categorical_crossentropy')

a = np.array(model.get_weights())         # save weights in a np.array of np.arrays
model.set_weights(a + 1)                  # add 1 to all weights in the neural network
b = np.array(model.get_weights())         # save weights a second time in a np.array of np.arrays
print(b - a)                              # print changes in weights

Jetez un œil à la page respective de la documentation des keras ici .

12
apitsch

Vous avez besoin de TensorFlow pour calculer le gradient symbolique. Voici un exemple de jouet utilisant Keras puis creusant un peu pour effectuer manuellement la descente pas à pas dans TensorFlow.

from keras.models import Sequential
from keras.layers import Dense, Activation
from keras import backend as k
from keras import losses
import numpy as np
import tensorflow as tf
from sklearn.metrics import mean_squared_error
from math import sqrt

model = Sequential()
model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation='relu'))
model.add(Dense(8, kernel_initializer='uniform', activation='relu'))
model.add(Dense(8, kernel_initializer='uniform', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

inputs = np.random.random((1, 8))
outputs = model.predict(inputs)
targets = np.random.random((1, 8))
rmse = sqrt(mean_squared_error(targets, outputs))

print("===BEFORE WALKING DOWN GRADIENT===")
print("outputs:\n", outputs)
print("targets:\n", targets)
print("RMSE:", rmse)


def descend(steps=40, learning_rate=100.0, learning_decay=0.95):
    for s in range(steps):

        # If your target changes, you need to update the loss
        loss = losses.mean_squared_error(targets, model.output)

        #  ===== Symbolic Gradient =====
        # Tensorflow Tensor Object
        gradients = k.gradients(loss, model.trainable_weights)

        # ===== Numerical gradient =====
        # Numpy ndarray Objcet
        evaluated_gradients = sess.run(gradients, feed_dict={model.input: inputs})

        # For every trainable layer in the network
        for i in range(len(model.trainable_weights)):

            layer = model.trainable_weights[i]  # Select the layer

            # And modify it explicitly in TensorFlow
            sess.run(tf.assign_sub(layer, learning_rate * evaluated_gradients[i]))

        # decrease the learning rate
        learning_rate *= learning_decay

        outputs = model.predict(inputs)
        rmse = sqrt(mean_squared_error(targets, outputs))

        print("RMSE:", rmse)


if __name__ == "__main__":
    # Begin TensorFlow
    sess = tf.InteractiveSession()
    sess.run(tf.initialize_all_variables())

    descend(steps=5)

    final_outputs = model.predict(inputs)
    final_rmse = sqrt(mean_squared_error(targets, final_outputs))

    print("===AFTER STEPPING DOWN GRADIENT===")
    print("outputs:\n", final_outputs)
    print("targets:\n", targets)

RÉSULTATS:

===BEFORE WALKING DOWN GRADIENT===
outputs:
 [[0.49995303 0.5000101  0.50001436 0.50001544 0.49998832 0.49991882
  0.49994195 0.4999649 ]]
targets:
 [[0.60111501 0.70807258 0.02058449 0.96990985 0.83244264 0.21233911
  0.18182497 0.18340451]]
RMSE: 0.33518919408969455
RMSE: 0.05748867468895
RMSE: 0.03369414290610595
RMSE: 0.021872132066183464
RMSE: 0.015070048653579693
RMSE: 0.01164369828903875
===AFTER STEPPING DOWN GRADIENT===
outputs:
 [[0.601743   0.707857   0.04268148 0.9536494  0.8448022  0.20864952
  0.17241994 0.17464897]]
targets:
 [[0.60111501 0.70807258 0.02058449 0.96990985 0.83244264 0.21233911
  0.18182497 0.18340451]]
4
birdmw