Après avoir formé un modèle dans Tensorflow:
- Comment enregistrez-vous le modèle formé?
- Comment restaurer ultérieurement ce modèle enregistré?
Après avoir formé un modèle dans Tensorflow:
Réponses:
tutoriel exhaustif et utile -> https://www.tensorflow.org/guide/saved_model
Guide détaillé de Keras pour enregistrer des modèles -> https://www.tensorflow.org/guide/keras/save_and_serialize
De la documentation:
# Create some variables.
v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
v2 = tf.get_variable("v2", shape=[5], initializer = tf.zeros_initializer)
inc_v1 = v1.assign(v1+1)
dec_v2 = v2.assign(v2-1)
# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, initialize the variables, do some work, and save the
# variables to disk.
with tf.Session() as sess:
sess.run(init_op)
# Do some work with the model.
inc_v1.op.run()
dec_v2.op.run()
# Save the variables to disk.
save_path = saver.save(sess, "/tmp/model.ckpt")
print("Model saved in path: %s" % save_path)
tf.reset_default_graph()
# Create some variables.
v1 = tf.get_variable("v1", shape=[3])
v2 = tf.get_variable("v2", shape=[5])
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
# Restore variables from disk.
saver.restore(sess, "/tmp/model.ckpt")
print("Model restored.")
# Check the values of the variables
print("v1 : %s" % v1.eval())
print("v2 : %s" % v2.eval())
Ceci est encore en version bêta, donc je déconseille pour l'instant. Si vous voulez toujours emprunter cette voie, voici le tf.saved_model
guide d'utilisation
simple_save
Beaucoup de bonne réponse, pour être complet j'ajouterai mes 2 cents: simple_save . Également un exemple de code autonome utilisant l' tf.data.Dataset
API.
Python 3; Tensorflow 1.14
import tensorflow as tf
from tensorflow.saved_model import tag_constants
with tf.Graph().as_default():
with tf.Session() as sess:
...
# Saving
inputs = {
"batch_size_placeholder": batch_size_placeholder,
"features_placeholder": features_placeholder,
"labels_placeholder": labels_placeholder,
}
outputs = {"prediction": model_output}
tf.saved_model.simple_save(
sess, 'path/to/your/location/', inputs, outputs
)
Restauration:
graph = tf.Graph()
with restored_graph.as_default():
with tf.Session() as sess:
tf.saved_model.loader.load(
sess,
[tag_constants.SERVING],
'path/to/your/location/',
)
batch_size_placeholder = graph.get_tensor_by_name('batch_size_placeholder:0')
features_placeholder = graph.get_tensor_by_name('features_placeholder:0')
labels_placeholder = graph.get_tensor_by_name('labels_placeholder:0')
prediction = restored_graph.get_tensor_by_name('dense/BiasAdd:0')
sess.run(prediction, feed_dict={
batch_size_placeholder: some_value,
features_placeholder: some_other_value,
labels_placeholder: another_value
})
Le code suivant génère des données aléatoires pour la démonstration.
Dataset
puis son Iterator
. Nous obtenons le tenseur généré par l'itérateur, appelé input_tensor
qui servira d'entrée à notre modèle.input_tensor
: d'un RNN bidirectionnel basé sur GRU suivi d'un classificateur dense. Parce que pourquoi pas.softmax_cross_entropy_with_logits
, optimisée avec Adam
. Après 2 époques (de 2 lots chacune), nous sauvegardons le modèle "entraîné" avec tf.saved_model.simple_save
. Si vous exécutez le code tel quel, le modèle sera enregistré dans un dossier appelé simple/
dans votre répertoire de travail actuel.tf.saved_model.loader.load
. Nous récupérons les espaces réservés et les logits avec graph.get_tensor_by_name
et l' Iterator
opération d'initialisation avec graph.get_operation_by_name
.Code:
import os
import shutil
import numpy as np
import tensorflow as tf
from tensorflow.python.saved_model import tag_constants
def model(graph, input_tensor):
"""Create the model which consists of
a bidirectional rnn (GRU(10)) followed by a dense classifier
Args:
graph (tf.Graph): Tensors' graph
input_tensor (tf.Tensor): Tensor fed as input to the model
Returns:
tf.Tensor: the model's output layer Tensor
"""
cell = tf.nn.rnn_cell.GRUCell(10)
with graph.as_default():
((fw_outputs, bw_outputs), (fw_state, bw_state)) = tf.nn.bidirectional_dynamic_rnn(
cell_fw=cell,
cell_bw=cell,
inputs=input_tensor,
sequence_length=[10] * 32,
dtype=tf.float32,
swap_memory=True,
scope=None)
outputs = tf.concat((fw_outputs, bw_outputs), 2)
mean = tf.reduce_mean(outputs, axis=1)
dense = tf.layers.dense(mean, 5, activation=None)
return dense
def get_opt_op(graph, logits, labels_tensor):
"""Create optimization operation from model's logits and labels
Args:
graph (tf.Graph): Tensors' graph
logits (tf.Tensor): The model's output without activation
labels_tensor (tf.Tensor): Target labels
Returns:
tf.Operation: the operation performing a stem of Adam optimizer
"""
with graph.as_default():
with tf.variable_scope('loss'):
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=labels_tensor, name='xent'),
name="mean-xent"
)
with tf.variable_scope('optimizer'):
opt_op = tf.train.AdamOptimizer(1e-2).minimize(loss)
return opt_op
if __name__ == '__main__':
# Set random seed for reproducibility
# and create synthetic data
np.random.seed(0)
features = np.random.randn(64, 10, 30)
labels = np.eye(5)[np.random.randint(0, 5, (64,))]
graph1 = tf.Graph()
with graph1.as_default():
# Random seed for reproducibility
tf.set_random_seed(0)
# Placeholders
batch_size_ph = tf.placeholder(tf.int64, name='batch_size_ph')
features_data_ph = tf.placeholder(tf.float32, [None, None, 30], 'features_data_ph')
labels_data_ph = tf.placeholder(tf.int32, [None, 5], 'labels_data_ph')
# Dataset
dataset = tf.data.Dataset.from_tensor_slices((features_data_ph, labels_data_ph))
dataset = dataset.batch(batch_size_ph)
iterator = tf.data.Iterator.from_structure(dataset.output_types, dataset.output_shapes)
dataset_init_op = iterator.make_initializer(dataset, name='dataset_init')
input_tensor, labels_tensor = iterator.get_next()
# Model
logits = model(graph1, input_tensor)
# Optimization
opt_op = get_opt_op(graph1, logits, labels_tensor)
with tf.Session(graph=graph1) as sess:
# Initialize variables
tf.global_variables_initializer().run(session=sess)
for epoch in range(3):
batch = 0
# Initialize dataset (could feed epochs in Dataset.repeat(epochs))
sess.run(
dataset_init_op,
feed_dict={
features_data_ph: features,
labels_data_ph: labels,
batch_size_ph: 32
})
values = []
while True:
try:
if epoch < 2:
# Training
_, value = sess.run([opt_op, logits])
print('Epoch {}, batch {} | Sample value: {}'.format(epoch, batch, value[0]))
batch += 1
else:
# Final inference
values.append(sess.run(logits))
print('Epoch {}, batch {} | Final inference | Sample value: {}'.format(epoch, batch, values[-1][0]))
batch += 1
except tf.errors.OutOfRangeError:
break
# Save model state
print('\nSaving...')
cwd = os.getcwd()
path = os.path.join(cwd, 'simple')
shutil.rmtree(path, ignore_errors=True)
inputs_dict = {
"batch_size_ph": batch_size_ph,
"features_data_ph": features_data_ph,
"labels_data_ph": labels_data_ph
}
outputs_dict = {
"logits": logits
}
tf.saved_model.simple_save(
sess, path, inputs_dict, outputs_dict
)
print('Ok')
# Restoring
graph2 = tf.Graph()
with graph2.as_default():
with tf.Session(graph=graph2) as sess:
# Restore saved values
print('\nRestoring...')
tf.saved_model.loader.load(
sess,
[tag_constants.SERVING],
path
)
print('Ok')
# Get restored placeholders
labels_data_ph = graph2.get_tensor_by_name('labels_data_ph:0')
features_data_ph = graph2.get_tensor_by_name('features_data_ph:0')
batch_size_ph = graph2.get_tensor_by_name('batch_size_ph:0')
# Get restored model output
restored_logits = graph2.get_tensor_by_name('dense/BiasAdd:0')
# Get dataset initializing operation
dataset_init_op = graph2.get_operation_by_name('dataset_init')
# Initialize restored dataset
sess.run(
dataset_init_op,
feed_dict={
features_data_ph: features,
labels_data_ph: labels,
batch_size_ph: 32
}
)
# Compute inference for both batches in dataset
restored_values = []
for i in range(2):
restored_values.append(sess.run(restored_logits))
print('Restored values: ', restored_values[i][0])
# Check if original inference and restored inference are equal
valid = all((v == rv).all() for v, rv in zip(values, restored_values))
print('\nInferences match: ', valid)
Cela imprimera:
$ python3 save_and_restore.py
Epoch 0, batch 0 | Sample value: [-0.13851789 -0.3087595 0.12804556 0.20013677 -0.08229901]
Epoch 0, batch 1 | Sample value: [-0.00555491 -0.04339041 -0.05111827 -0.2480045 -0.00107776]
Epoch 1, batch 0 | Sample value: [-0.19321944 -0.2104792 -0.00602257 0.07465433 0.11674127]
Epoch 1, batch 1 | Sample value: [-0.05275984 0.05981954 -0.15913513 -0.3244143 0.10673307]
Epoch 2, batch 0 | Final inference | Sample value: [-0.26331693 -0.13013336 -0.12553 -0.04276478 0.2933622 ]
Epoch 2, batch 1 | Final inference | Sample value: [-0.07730117 0.11119192 -0.20817074 -0.35660955 0.16990358]
Saving...
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: b'/some/path/simple/saved_model.pb'
Ok
Restoring...
INFO:tensorflow:Restoring parameters from b'/some/path/simple/variables/variables'
Ok
Restored values: [-0.26331693 -0.13013336 -0.12553 -0.04276478 0.2933622 ]
Restored values: [-0.07730117 0.11119192 -0.20817074 -0.35660955 0.16990358]
Inferences match: True
tf.contrib.layers
?
[n.name for n in graph2.as_graph_def().node]
. Comme le dit la documentation, la sauvegarde simple vise à simplifier l'interaction avec le service tensorflow, c'est le point des arguments; d'autres variables sont cependant toujours restaurées, sinon l'inférence ne se produirait pas. Saisissez simplement vos variables d'intérêt comme je l'ai fait dans l'exemple. Consultez la documentation
global_step
argument, si vous vous arrêtez puis essayez de reprendre la formation, il pensera que vous êtes une étape. Cela gâchera au moins vos visualisations de tensorboard
J'améliore ma réponse pour ajouter plus de détails sur la sauvegarde et la restauration des modèles.
Dans (et après) la version 0.11 de Tensorflow :
Enregistrez le modèle:
import tensorflow as tf
#Prepare to feed input, i.e. feed_dict and placeholders
w1 = tf.placeholder("float", name="w1")
w2 = tf.placeholder("float", name="w2")
b1= tf.Variable(2.0,name="bias")
feed_dict ={w1:4,w2:8}
#Define a test operation that we will restore
w3 = tf.add(w1,w2)
w4 = tf.multiply(w3,b1,name="op_to_restore")
sess = tf.Session()
sess.run(tf.global_variables_initializer())
#Create a saver object which will save all the variables
saver = tf.train.Saver()
#Run the operation by feeding input
print sess.run(w4,feed_dict)
#Prints 24 which is sum of (w1+w2)*b1
#Now, save the graph
saver.save(sess, 'my_test_model',global_step=1000)
Restaurer le modèle:
import tensorflow as tf
sess=tf.Session()
#First let's load meta graph and restore weights
saver = tf.train.import_meta_graph('my_test_model-1000.meta')
saver.restore(sess,tf.train.latest_checkpoint('./'))
# Access saved Variables directly
print(sess.run('bias:0'))
# This will print 2, which is the value of bias that we saved
# Now, let's access and create placeholders variables and
# create feed-dict to feed new data
graph = tf.get_default_graph()
w1 = graph.get_tensor_by_name("w1:0")
w2 = graph.get_tensor_by_name("w2:0")
feed_dict ={w1:13.0,w2:17.0}
#Now, access the op that you want to run.
op_to_restore = graph.get_tensor_by_name("op_to_restore:0")
print sess.run(op_to_restore,feed_dict)
#This will print 60 which is calculated
Ceci et quelques cas d'utilisation plus avancés ont été très bien expliqués ici.
Un tutoriel complet rapide pour enregistrer et restaurer les modèles Tensorflow
:0
aux noms?
Dans (et après) la version 0.11.0RC1 de TensorFlow, vous pouvez enregistrer et restaurer votre modèle directement en appelant tf.train.export_meta_graph
et tf.train.import_meta_graph
selon https://www.tensorflow.org/programmers_guide/meta_graph .
w1 = tf.Variable(tf.truncated_normal(shape=[10]), name='w1')
w2 = tf.Variable(tf.truncated_normal(shape=[20]), name='w2')
tf.add_to_collection('vars', w1)
tf.add_to_collection('vars', w2)
saver = tf.train.Saver()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, 'my-model')
# `save` method will call `export_meta_graph` implicitly.
# you will get saved graph files:my-model.meta
sess = tf.Session()
new_saver = tf.train.import_meta_graph('my-model.meta')
new_saver.restore(sess, tf.train.latest_checkpoint('./'))
all_vars = tf.get_collection('vars')
for v in all_vars:
v_ = sess.run(v)
print(v_)
<built-in function TF_Run> returned a result with an error set
tf.get_variable_scope().reuse_variables()
suivi de var = tf.get_variable("varname")
. Cela me donne l'erreur: "ValueError: la variable varname n'existe pas ou n'a pas été créée avec tf.get_variable ()." Pourquoi? Cela ne devrait-il pas être possible?
Pour la version TensorFlow <0.11.0RC1:
Les points de contrôle enregistrés contiennent des valeurs pour les Variable
s dans votre modèle, pas le modèle / graphique lui-même, ce qui signifie que le graphique doit être le même lorsque vous restaurez le point de contrôle.
Voici un exemple de régression linéaire où il y a une boucle d'apprentissage qui enregistre les points de contrôle des variables et une section d'évaluation qui restaurera les variables enregistrées lors d'une exécution précédente et calculera les prédictions. Bien sûr, vous pouvez également restaurer des variables et continuer la formation si vous le souhaitez.
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
w = tf.Variable(tf.zeros([1, 1], dtype=tf.float32))
b = tf.Variable(tf.ones([1, 1], dtype=tf.float32))
y_hat = tf.add(b, tf.matmul(x, w))
...more setup for optimization and what not...
saver = tf.train.Saver() # defaults to saving all variables - in this case w and b
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
if FLAGS.train:
for i in xrange(FLAGS.training_steps):
...training loop...
if (i + 1) % FLAGS.checkpoint_steps == 0:
saver.save(sess, FLAGS.checkpoint_dir + 'model.ckpt',
global_step=i+1)
else:
# Here's where you're restoring the variables w and b.
# Note that the graph is exactly as it was when the variables were
# saved in a prior training run.
ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
else:
...no checkpoint found...
# Now you can run the model to get predictions
batch_x = ...load some data...
predictions = sess.run(y_hat, feed_dict={x: batch_x})
Voici les documents pour Variable
s, qui couvrent la sauvegarde et la restauration. Et voici les documents pour le Saver
.
batch_x
doit être? Binaire? Tableau Numpy?
undefined
. Pouvez-vous me dire quelle est la définition de FLAGS pour ce code. @RyanSepassi
Mon environnement: Python 3.6, Tensorflow 1.3.0
Bien qu'il y ait eu de nombreuses solutions, la plupart d'entre elles sont basées sur tf.train.Saver
. Lorsque nous chargeons un .ckpt
sauvé par Saver
, nous devons redéfinir soit le réseau tensorflow ou utiliser un bizarre nom et dur rappeler, par exemple 'placehold_0:0'
, 'dense/Adam/Weight:0'
. Ici, je recommande d'utiliser tf.saved_model
, un exemple le plus simple donné ci-dessous, vous pouvez en apprendre plus sur Serving a TensorFlow Model :
Enregistrez le modèle:
import tensorflow as tf
# define the tensorflow network and do some trains
x = tf.placeholder("float", name="x")
w = tf.Variable(2.0, name="w")
b = tf.Variable(0.0, name="bias")
h = tf.multiply(x, w)
y = tf.add(h, b, name="y")
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# save the model
export_path = './savedmodel'
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_y = tf.saved_model.utils.build_tensor_info(y)
prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={'x_input': tensor_info_x},
outputs={'y_output': tensor_info_y},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
prediction_signature
},
)
builder.save()
Chargez le modèle:
import tensorflow as tf
sess=tf.Session()
signature_key = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
input_key = 'x_input'
output_key = 'y_output'
export_path = './savedmodel'
meta_graph_def = tf.saved_model.loader.load(
sess,
[tf.saved_model.tag_constants.SERVING],
export_path)
signature = meta_graph_def.signature_def
x_tensor_name = signature[signature_key].inputs[input_key].name
y_tensor_name = signature[signature_key].outputs[output_key].name
x = sess.graph.get_tensor_by_name(x_tensor_name)
y = sess.graph.get_tensor_by_name(y_tensor_name)
y_out = sess.run(y, {x: 3.0})
Le modèle comporte deux parties, la définition du modèle, enregistrée par Supervisor
comme graph.pbtxt
dans le répertoire du modèle et les valeurs numériques des tenseurs, enregistrées dans des fichiers de point de contrôle comme model.ckpt-1003418
.
La définition du modèle peut être restaurée à l'aide tf.import_graph_def
et les poids sont restaurés à l'aide Saver
.
Cependant, Saver
utilise une collection spéciale contenant une liste de variables attachées au graphique du modèle, et cette collection n'est pas initialisée à l'aide d'import_graph_def, vous ne pouvez donc pas utiliser les deux ensemble pour le moment (c'est sur notre feuille de route à corriger). Pour l'instant, vous devez utiliser l'approche de Ryan Sepassi - construire manuellement un graphique avec des noms de nœuds identiques, et utiliser Saver
pour y charger les poids.
(Alternativement, vous pouvez le pirater en utilisant en utilisant import_graph_def
, en créant des variables manuellement et en utilisant tf.add_to_collection(tf.GraphKeys.VARIABLES, variable)
pour chaque variable, puis en utilisant Saver
)
Vous pouvez également utiliser cette méthode plus facilement.
W1 = tf.Variable(tf.truncated_normal([6, 6, 1, K], stddev=0.1), name="W1")
B1 = tf.Variable(tf.constant(0.1, tf.float32, [K]), name="B1")
Similarly, W2, B2, W3, .....
Saver
et enregistrez-lamodel_saver = tf.train.Saver()
# Train the model and save it in the end
model_saver.save(session, "saved_models/CNN_New.ckpt")
with tf.Session(graph=graph_cnn) as session:
model_saver.restore(session, "saved_models/CNN_New.ckpt")
print("Model restored.")
print('Initialized')
W1 = session.run(W1)
print(W1)
Lors de l'exécution dans une instance python différente, utilisez
with tf.Session() as sess:
# Restore latest checkpoint
saver.restore(sess, tf.train.latest_checkpoint('saved_model/.'))
# Initalize the variables
sess.run(tf.global_variables_initializer())
# Get default graph (supply your custom graph if you have one)
graph = tf.get_default_graph()
# It will give tensor object
W1 = graph.get_tensor_by_name('W1:0')
# To get the value (numpy array)
W1_value = session.run(W1)
Dans la plupart des cas, l'enregistrement et la restauration à partir du disque à l'aide de tf.train.Saver
est votre meilleure option:
... # build your model
saver = tf.train.Saver()
with tf.Session() as sess:
... # train the model
saver.save(sess, "/tmp/my_great_model")
with tf.Session() as sess:
saver.restore(sess, "/tmp/my_great_model")
... # use the model
Vous pouvez également enregistrer / restaurer la structure graphique elle-même (voir la documentation MetaGraph pour plus de détails). Par défaut, l' Saver
enregistre la structure du graphique dans un .meta
fichier. Vous pouvez appeler import_meta_graph()
pour le restaurer. Il restaure la structure du graphique et renvoie un Saver
que vous pouvez utiliser pour restaurer l'état du modèle:
saver = tf.train.import_meta_graph("/tmp/my_great_model.meta")
with tf.Session() as sess:
saver.restore(sess, "/tmp/my_great_model")
... # use the model
Cependant, il y a des cas où vous avez besoin de quelque chose de beaucoup plus rapide. Par exemple, si vous implémentez un arrêt anticipé, vous souhaitez enregistrer les points de contrôle chaque fois que le modèle s'améliore pendant la formation (mesuré sur l'ensemble de validation), puis s'il n'y a pas de progrès pendant un certain temps, vous souhaitez revenir au meilleur modèle. Si vous enregistrez le modèle sur le disque chaque fois qu'il s'améliore, cela ralentit considérablement la formation. L'astuce consiste à enregistrer les états des variables en mémoire , puis à les restaurer plus tard:
... # build your model
# get a handle on the graph nodes we need to save/restore the model
graph = tf.get_default_graph()
gvars = graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
assign_ops = [graph.get_operation_by_name(v.op.name + "/Assign") for v in gvars]
init_values = [assign_op.inputs[1] for assign_op in assign_ops]
with tf.Session() as sess:
... # train the model
# when needed, save the model state to memory
gvars_state = sess.run(gvars)
# when needed, restore the model state
feed_dict = {init_value: val
for init_value, val in zip(init_values, gvars_state)}
sess.run(assign_ops, feed_dict=feed_dict)
Une explication rapide: lorsque vous créez une variable X
, TensorFlow crée automatiquement une opération d'affectationX/Assign
pour définir la valeur initiale de la variable. Au lieu de créer des espaces réservés et des opérations d'affectation supplémentaires (ce qui rendrait le graphique désordonné), nous utilisons simplement ces opérations d'affectation existantes. La première entrée de chaque affectation op est une référence à la variable qu'elle est censée initialiser, et la deuxième entrée ( assign_op.inputs[1]
) est la valeur initiale. Donc, pour définir la valeur que nous voulons (au lieu de la valeur initiale), nous devons utiliser a feed_dict
et remplacer la valeur initiale. Oui, TensorFlow vous permet de fournir une valeur pour n'importe quelle opération, pas seulement pour les espaces réservés, donc cela fonctionne très bien.
Comme l'a dit Yaroslav, vous pouvez pirater la restauration à partir d'un graph_def et d'un point de contrôle en important le graphique, en créant manuellement des variables, puis en utilisant un économiseur.
J'ai implémenté cela pour mon usage personnel, donc je pensais partager le code ici.
Lien: https://gist.github.com/nikitakit/6ef3b72be67b86cb7868
(Il s'agit bien sûr d'un hack, et rien ne garantit que les modèles enregistrés de cette manière resteront lisibles dans les futures versions de TensorFlow.)
S'il s'agit d'un modèle enregistré en interne, vous spécifiez simplement un restaurateur pour toutes les variables comme
restorer = tf.train.Saver(tf.all_variables())
et l'utiliser pour restaurer des variables dans une session en cours:
restorer.restore(self._sess, model_file)
Pour le modèle externe, vous devez spécifier le mappage entre ses noms de variables et vos noms de variables. Vous pouvez afficher les noms des variables de modèle à l'aide de la commande
python /path/to/tensorflow/tensorflow/python/tools/inspect_checkpoint.py --file_name=/path/to/pretrained_model/model.ckpt
Le script inspect_checkpoint.py se trouve dans le dossier './tensorflow/python/tools' de la source Tensorflow.
Pour spécifier le mappage, vous pouvez utiliser mon Tensorflow-Worklab , qui contient un ensemble de classes et de scripts pour former et recycler différents modèles. Il comprend un exemple de recyclage des modèles ResNet, situé ici
all_variables()
est désormais obsolète
Voici ma solution simple pour les deux cas de base différents selon que vous souhaitez charger le graphique à partir d'un fichier ou le créer pendant l'exécution.
Cette réponse est valable pour Tensorflow 0.12+ (y compris 1.0).
graph = ... # build the graph
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.save(sess, 'my-model')
graph = ... # build the graph
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.restore(sess, tf.train.latest_checkpoint('./'))
# now you can use the graph, continue training or whatever
Lorsque vous utilisez cette technique, assurez-vous que toutes vos couches / variables ont explicitement défini des noms uniques.Sinon, Tensorflow rendra les noms uniques eux-mêmes et ils seront donc différents des noms stockés dans le fichier. Ce n'est pas un problème dans la technique précédente, car les noms sont "mutilés" de la même manière lors du chargement et de l'enregistrement.
graph = ... # build the graph
for op in [ ... ]: # operators you want to use after restoring the model
tf.add_to_collection('ops_to_restore', op)
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.save(sess, 'my-model')
with ... as sess: # your session object
saver = tf.train.import_meta_graph('my-model.meta')
saver.restore(sess, tf.train.latest_checkpoint('./'))
ops = tf.get_collection('ops_to_restore') # here are your operators in the same order in which you saved them to the collection
global_step
variable et les moyennes mobiles de normalisation par lots sont des variables non entraînables, mais les deux valent vraiment la peine d'être sauvegardées. En outre, vous devez distinguer plus clairement la construction du graphique de l'exécution de la session, par exemple Saver(...).save()
, vous créerez de nouveaux nœuds chaque fois que vous l'exécuterez. Probablement pas ce que vous voulez. Et il y a plus ...: /
Vous pouvez également consulter des exemples dans TensorFlow / skflow , qui propose des méthodes save
et restore
qui peuvent vous aider à gérer facilement vos modèles. Il possède des paramètres que vous pouvez également contrôler à quelle fréquence vous souhaitez sauvegarder votre modèle.
Si vous utilisez tf.train.MonitoredTrainingSession comme session par défaut, vous n'avez pas besoin d'ajouter de code supplémentaire pour enregistrer / restaurer des choses. Passez simplement un nom de répertoire de point de contrôle au constructeur de MonitoredTrainingSession, il utilisera des hooks de session pour les gérer.
Toutes les réponses ici sont excellentes, mais je veux ajouter deux choses.
Tout d'abord, pour développer la réponse de @ user7505159, le "./" peut être important à ajouter au début du nom de fichier que vous restaurez.
Par exemple, vous pouvez enregistrer un graphique sans "./" dans le nom de fichier comme ceci:
# Some graph defined up here with specific names
saver = tf.train.Saver()
save_file = 'model.ckpt'
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.save(sess, save_file)
Mais pour restaurer le graphique, vous devrez peut-être ajouter un "./" au nom_fichier:
# Same graph defined up here
saver = tf.train.Saver()
save_file = './' + 'model.ckpt' # String addition used for emphasis
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.restore(sess, save_file)
Vous n'aurez pas toujours besoin du "./", mais cela peut poser des problèmes en fonction de votre environnement et de la version de TensorFlow.
Il faut également mentionner que le sess.run(tf.global_variables_initializer())
peut être important avant de restaurer la session.
Si vous recevez une erreur concernant les variables non initialisées lorsque vous essayez de restaurer une session enregistrée, assurez-vous de l'inclure sess.run(tf.global_variables_initializer())
avant la saver.restore(sess, save_file)
ligne. Cela peut vous éviter des maux de tête.
Selon la nouvelle version Tensorflow, tf.train.Checkpoint
est le moyen préférable d'enregistrer et de restaurer un modèle:
Checkpoint.save
etCheckpoint.restore
écrire et lire des points de contrôle basés sur des objets, contrairement à tf.train.Saver qui écrit et lit des points de contrôle basés sur variable.name. Le point de contrôle basé sur les objets enregistre un graphique des dépendances entre les objets Python (couches, optimiseurs, variables, etc.) avec des bords nommés, et ce graphique est utilisé pour faire correspondre les variables lors de la restauration d'un point de contrôle. Il peut être plus robuste aux modifications du programme Python et aide à prendre en charge la restauration lors de la création de variables lors de l'exécution avec impatience. Préféreztf.train.Checkpoint
letf.train.Saver
nouveau code .
Voici un exemple:
import tensorflow as tf
import os
tf.enable_eager_execution()
checkpoint_directory = "/tmp/training_checkpoints"
checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt")
checkpoint = tf.train.Checkpoint(optimizer=optimizer, model=model)
status = checkpoint.restore(tf.train.latest_checkpoint(checkpoint_directory))
for _ in range(num_training_steps):
optimizer.minimize( ... ) # Variables will be restored on creation.
status.assert_consumed() # Optional sanity checks.
checkpoint.save(file_prefix=checkpoint_prefix)
Pour tensorflow 2.0 , c'est aussi simple que
# Save the model model.save('path_to_my_model.h5')
Restaurer:
new_model = tensorflow.keras.models.load_model('path_to_my_model.h5')
TF2.0
Je vois d'excellentes réponses pour enregistrer des modèles à l'aide de TF1.x. Je veux fournir quelques conseils supplémentaires pour enregistrer des tensorflow.keras
modèles, ce qui est un peu compliqué car il existe de nombreuses façons de sauvegarder un modèle.
Ici, je fournis un exemple d'enregistrement d'un tensorflow.keras
modèle dans un model_path
dossier sous le répertoire actuel. Cela fonctionne bien avec le tensorflow le plus récent (TF2.0). Je mettrai à jour cette description en cas de changement dans un avenir proche.
import tensorflow as tf
from tensorflow import keras
mnist = tf.keras.datasets.mnist
#import data
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# create a model
def create_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
# compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
# Create a basic model instance
model=create_model()
model.fit(x_train, y_train, epochs=1)
loss, acc = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
# Save entire model to a HDF5 file
model.save('./model_path/my_model.h5')
# Recreate the exact same model, including weights and optimizer.
new_model = keras.models.load_model('./model_path/my_model.h5')
loss, acc = new_model.evaluate(x_test, y_test)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
Si vous souhaitez enregistrer uniquement les poids du modèle, puis charger des poids pour restaurer le modèle,
model.fit(x_train, y_train, epochs=5)
loss, acc = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
# Save the weights
model.save_weights('./checkpoints/my_checkpoint')
# Restore the weights
model = create_model()
model.load_weights('./checkpoints/my_checkpoint')
loss,acc = model.evaluate(x_test, y_test)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
# include the epoch in the file name. (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(
checkpoint_path, verbose=1, save_weights_only=True,
# Save weights, every 5-epochs.
period=5)
model = create_model()
model.save_weights(checkpoint_path.format(epoch=0))
model.fit(train_images, train_labels,
epochs = 50, callbacks = [cp_callback],
validation_data = (test_images,test_labels),
verbose=0)
latest = tf.train.latest_checkpoint(checkpoint_dir)
new_model = create_model()
new_model.load_weights(latest)
loss, acc = new_model.evaluate(test_images, test_labels)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
import tensorflow as tf
from tensorflow import keras
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
# Custom Loss1 (for example)
@tf.function()
def customLoss1(yTrue,yPred):
return tf.reduce_mean(yTrue-yPred)
# Custom Loss2 (for example)
@tf.function()
def customLoss2(yTrue, yPred):
return tf.reduce_mean(tf.square(tf.subtract(yTrue,yPred)))
def create_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy', customLoss1, customLoss2])
return model
# Create a basic model instance
model=create_model()
# Fit and evaluate model
model.fit(x_train, y_train, epochs=1)
loss, acc,loss1, loss2 = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
model.save("./model.h5")
new_model=tf.keras.models.load_model("./model.h5",custom_objects={'customLoss1':customLoss1,'customLoss2':customLoss2})
Lorsque nous avons des opérations personnalisées comme dans le cas suivant ( tf.tile
), nous devons créer une fonction et encapsuler avec une couche Lambda. Sinon, le modèle ne peut pas être enregistré.
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Lambda
from tensorflow.keras import Model
def my_fun(a):
out = tf.tile(a, (1, tf.shape(a)[0]))
return out
a = Input(shape=(10,))
#out = tf.tile(a, (1, tf.shape(a)[0]))
out = Lambda(lambda x : my_fun(x))(a)
model = Model(a, out)
x = np.zeros((50,10), dtype=np.float32)
print(model(x).numpy())
model.save('my_model.h5')
#load the model
new_model=tf.keras.models.load_model("my_model.h5")
Je pense avoir couvert quelques-unes des nombreuses façons de sauvegarder le modèle tf.keras. Cependant, il existe de nombreuses autres façons. Veuillez commenter ci-dessous si vous voyez que votre cas d'utilisation n'est pas couvert ci-dessus. Merci!
Vous pouvez enregistrer les variables dans le réseau en utilisant
saver = tf.train.Saver()
saver.save(sess, 'path of save/fileName.ckpt')
Pour restaurer le réseau pour une réutilisation ultérieure ou dans un autre script, utilisez:
saver = tf.train.Saver()
saver.restore(sess, tf.train.latest_checkpoint('path of save/')
sess.run(....)
Les points importants:
sess
doit être le même entre la première et la dernière exécution (structure cohérente). saver.restore
a besoin du chemin du dossier des fichiers enregistrés, pas d'un chemin de fichier individuel. Où que vous souhaitiez enregistrer le modèle,
self.saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
...
self.saver.save(sess, filename)
Assurez-vous que vous tf.Variable
avez tous des noms, car vous souhaiterez peut-être les restaurer ultérieurement en utilisant leurs noms. Et où vous voulez prédire,
saver = tf.train.import_meta_graph(filename)
name = 'name given when you saved the file'
with tf.Session() as sess:
saver.restore(sess, name)
print(sess.run('W1:0')) #example to retrieve by variable name
Assurez-vous que l'économiseur s'exécute dans la session correspondante. N'oubliez pas que si vous utilisez le tf.train.latest_checkpoint('./')
, seul le dernier point de contrôle sera utilisé.
Pour tensorflow-2.0
c'est très simple.
import tensorflow as tf
model.save("model_name")
model = tf.keras.models.load_model('model_name')
Suite à la réponse de @Vishnuvardhan Janapati, voici une autre façon d'enregistrer et de recharger le modèle avec une couche / métrique / perte personnalisée sous TensorFlow 2.0.0
import tensorflow as tf
from tensorflow.keras.layers import Layer
from tensorflow.keras.utils.generic_utils import get_custom_objects
# custom loss (for example)
def custom_loss(y_true,y_pred):
return tf.reduce_mean(y_true - y_pred)
get_custom_objects().update({'custom_loss': custom_loss})
# custom loss (for example)
class CustomLayer(Layer):
def __init__(self, ...):
...
# define custom layer and all necessary custom operations inside custom layer
get_custom_objects().update({'CustomLayer': CustomLayer})
De cette façon, une fois que vous avez exécuté de tels codes et enregistré votre modèle avec tf.keras.models.save_model
ou model.save
ou ModelCheckpoint
rappel, vous pouvez recharger votre modèle sans avoir besoin d'objets personnalisés précis, aussi simple que
new_model = tf.keras.models.load_model("./model.h5"})
Dans la nouvelle version de tensorflow 2.0, le processus de sauvegarde / chargement d'un modèle est beaucoup plus facile. En raison de l'implémentation de l'API Keras, une API de haut niveau pour TensorFlow.
Pour enregistrer un modèle: consultez la documentation pour référence: https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/models/save_model
tf.keras.models.save_model(model_name, filepath, save_format)
Pour charger un modèle:
https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/models/load_model
model = tf.keras.models.load_model(filepath)
Voici un exemple simple utilisant le format Tensorflow 2.0 SavedModel (qui est le format recommandé, selon les documents ) pour un classificateur de jeu de données MNIST simple, en utilisant l'API fonctionnelle Keras sans trop de fantaisie:
# Imports
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Flatten
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt
# Load data
mnist = tf.keras.datasets.mnist # 28 x 28
(x_train,y_train), (x_test, y_test) = mnist.load_data()
# Normalize pixels [0,255] -> [0,1]
x_train = tf.keras.utils.normalize(x_train,axis=1)
x_test = tf.keras.utils.normalize(x_test,axis=1)
# Create model
input = Input(shape=(28,28), dtype='float64', name='graph_input')
x = Flatten()(input)
x = Dense(128, activation='relu')(x)
x = Dense(128, activation='relu')(x)
output = Dense(10, activation='softmax', name='graph_output', dtype='float64')(x)
model = Model(inputs=input, outputs=output)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Train
model.fit(x_train, y_train, epochs=3)
# Save model in SavedModel format (Tensorflow 2.0)
export_path = 'model'
tf.saved_model.save(model, export_path)
# ... possibly another python program
# Reload model
loaded_model = tf.keras.models.load_model(export_path)
# Get image sample for testing
index = 0
img = x_test[index] # I normalized the image on a previous step
# Predict using the signature definition (Tensorflow 2.0)
predict = loaded_model.signatures["serving_default"]
prediction = predict(tf.constant(img))
# Show results
print(np.argmax(prediction['graph_output'])) # prints the class number
plt.imshow(x_test[index], cmap=plt.cm.binary) # prints the image
Qu'est-ce que c'est serving_default
?
Il s'agit du nom de la signature par défaut du tag que vous avez sélectionné (dans ce cas, le serve
tag par défaut a été sélectionné). Également, ici explique comment trouver les balises et les signatures d'un modèle à l'aide saved_model_cli
.
Avertissements
Ce n'est qu'un exemple de base si vous voulez simplement le mettre en service, mais ce n'est en aucun cas une réponse complète - je pourrai peut-être le mettre à jour à l'avenir. Je voulais juste donner un exemple simple en utilisant leSavedModel
TF 2.0 car je n'en ai vu aucun, même si simple, nulle part.
@ La réponse de Tom est un exemple de SavedModel, mais cela ne fonctionnera pas sur Tensorflow 2.0, car malheureusement il y a des changements de rupture.
@ La réponse de Vishnuvardhan Janapati dit TF 2.0, mais ce n'est pas pour le format SavedModel.