Depois de treinar um modelo no Tensorflow:
- Como você salva o modelo treinado?
- Como você mais tarde restaura esse modelo salvo?
Depois de treinar um modelo no Tensorflow:
Respostas:
tutorial completo e útil -> https://www.tensorflow.org/guide/saved_model
Guia detalhado de Keras para salvar modelos -> https://www.tensorflow.org/guide/keras/save_and_serialize
Dos documentos:
# 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())
Ainda é beta, por isso não aconselho por enquanto. Se você ainda quiser seguir esse caminho, aqui está o tf.saved_model
guia de uso
simple_save
Muitas boas respostas, para completar, adicionarei meus 2 centavos: simple_save . Também um exemplo de código independente usando a 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
)
Restaurando:
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
})
O código a seguir gera dados aleatórios para a demonstração.
Dataset
e então é Iterator
. Nós obtemos o tensor gerado pelo iterador, chamado input_tensor
que servirá como entrada para o nosso modelo.input_tensor
: um RNN bidirecional baseado em GRU, seguido por um classificador denso. Porque porque não?softmax_cross_entropy_with_logits
otimizada com Adam
. Após 2 épocas (de 2 lotes cada), salvamos o modelo "treinado" tf.saved_model.simple_save
. Se você executar o código como está, o modelo será salvo em uma pasta chamada simple/
no seu diretório de trabalho atual.tf.saved_model.loader.load
. Pegamos os espaços reservados e logits com graph.get_tensor_by_name
e a Iterator
operação de inicialização com graph.get_operation_by_name
.Código:
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)
Isso imprimirá:
$ 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]
. Como a documentação diz, o save simples visa simplificar a interação com a veiculação do tensorflow, esse é o objetivo dos argumentos; outras variáveis ainda são restauradas, caso contrário, a inferência não aconteceria. Basta pegar suas variáveis de interesse, como fiz no exemplo. Verifique a documentação
global_step
como argumento, se você parar e tentar retomar o treinamento, ele pensará que você é um passo. Vai estragar suas visualizações tensorboard no mínimo
Estou melhorando minha resposta para adicionar mais detalhes para salvar e restaurar modelos.
Na (e depois) versão 0.11 do Tensorflow :
Salve o modelo:
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)
Restaure o modelo:
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
Este e alguns casos de uso mais avançados foram explicados muito bem aqui.
Um tutorial completo rápido para salvar e restaurar modelos do Tensorflow
:0
os nomes?
Na versão 0.11.0RC1 (e depois) do TensorFlow, você pode salvar e restaurar seu modelo diretamente ligando tf.train.export_meta_graph
e de tf.train.import_meta_graph
acordo com 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()
seguido por var = tf.get_variable("varname")
. Isso me dá o erro: "ValueError: variável varname não existe ou não foi criado com tf.get_variable ()." Por quê? Isso não deveria ser possível?
Para a versão TensorFlow <0.11.0RC1:
Os pontos de verificação salvos contêm valores para os Variable
s no seu modelo, não o modelo / gráfico em si, o que significa que o gráfico deve ser o mesmo quando você restaurar o ponto de verificação.
Aqui está um exemplo de regressão linear em que há um ciclo de treinamento que salva pontos de verificação variáveis e uma seção de avaliação que restaura as variáveis salvas em uma execução anterior e prediz a computação. Obviamente, você também pode restaurar variáveis e continuar o treinamento, se desejar.
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})
Aqui estão os documentos para Variable
s, que abrangem salvar e restaurar. E aqui estão os documentos para o Saver
.
batch_x
precisa estar? Binário? Matriz numpy?
undefined
. Você pode me dizer qual é def de FLAGS para este código. @RyanSepassi
Meu ambiente: Python 3.6, Tensorflow 1.3.0
Embora tenha havido muitas soluções, a maioria delas é baseada tf.train.Saver
. Quando carregar um .ckpt
salvo por Saver
, temos de redefinir tanto a rede tensorflow ou usar algum nome estranho e hard-lembrado, por exemplo 'placehold_0:0'
, 'dense/Adam/Weight:0'
. Aqui eu recomendo usar tf.saved_model
, um exemplo mais simples dado abaixo, você pode aprender mais sobre Servindo um Modelo TensorFlow :
Salve o modelo:
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()
Carregue o modelo:
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})
Existem duas partes no modelo, a definição do modelo, salva Supervisor
como graph.pbtxt
no diretório do modelo e os valores numéricos dos tensores, salvos em arquivos de ponto de verificação como model.ckpt-1003418
.
A definição do modelo pode ser restaurada usando tf.import_graph_def
e os pesos são restaurados usando Saver
.
No entanto, Saver
usa uma lista especial de retenção de variáveis anexadas ao modelo Graph, e essa coleção não é inicializada usando import_graph_def; portanto, você não pode usar as duas juntas no momento (está em nosso roteiro para corrigir). Por enquanto, você precisa usar a abordagem de Ryan Sepassi - construa manualmente um gráfico com nomes de nó idênticos e use Saver
para carregar os pesos nele.
(Como alternativa, você pode cortá-lo usando import_graph_def
, criando variáveis manualmente e usando tf.add_to_collection(tf.GraphKeys.VARIABLES, variable)
para cada variável e depois usando Saver
)
Você também pode seguir esse caminho mais fácil.
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
e salve-amodel_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)
Durante a execução em diferentes instâncias python, use
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)
Na maioria dos casos, salvar e restaurar do disco usando a tf.train.Saver
é a sua melhor opção:
... # 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
Você também pode salvar / restaurar a própria estrutura do gráfico (consulte a documentação do MetaGraph para obter detalhes). Por padrão, Saver
salva a estrutura do gráfico em um .meta
arquivo. Você pode ligar import_meta_graph()
para restaurá-lo. Restaura a estrutura do gráfico e retorna um Saver
que você pode usar para restaurar o estado do modelo:
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
No entanto, há casos em que você precisa de algo muito mais rápido. Por exemplo, se você implementar uma parada antecipada, deseje salvar os pontos de verificação sempre que o modelo melhorar durante o treinamento (conforme medido no conjunto de validação); se não houver progresso por algum tempo, será necessário reverter para o melhor modelo. Se você salvar o modelo em disco toda vez que ele melhorar, ele reduzirá tremendamente o treinamento. O truque é salvar os estados das variáveis na memória e restaurá-los mais tarde:
... # 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)
Uma explicação rápida: quando você cria uma variável X
, o TensorFlow cria automaticamente uma operação de atribuição X/Assign
para definir o valor inicial da variável. Em vez de criar espaços reservados e operações extras de atribuição (o que deixaria o gráfico confuso), apenas usamos essas operações existentes. A primeira entrada de cada atribuição op é uma referência à variável que ela deve inicializar, e a segunda entrada ( assign_op.inputs[1]
) é o valor inicial. Portanto, para definir qualquer valor que desejarmos (em vez do valor inicial), precisamos usar feed_dict
ae substituir o valor inicial. Sim, o TensorFlow permite que você alimente um valor para qualquer operação, não apenas para espaços reservados, portanto, isso funciona bem.
Como Yaroslav disse, você pode hackear a restauração de um graph_def e ponto de verificação importando o gráfico, criando manualmente variáveis e, em seguida, usando um Saver.
Eu implementei isso para meu uso pessoal, então eu gostaria de compartilhar o código aqui.
Link: https://gist.github.com/nikitakit/6ef3b72be67b86cb7868
(Obviamente, isso é um hack e não há garantia de que os modelos salvos dessa maneira permanecerão legíveis em versões futuras do TensorFlow.)
Se for um modelo salvo internamente, basta especificar um restaurador para todas as variáveis como
restorer = tf.train.Saver(tf.all_variables())
e use-o para restaurar variáveis em uma sessão atual:
restorer.restore(self._sess, model_file)
Para o modelo externo, você precisa especificar o mapeamento dos nomes de suas variáveis para seus nomes de variáveis. Você pode visualizar os nomes das variáveis do modelo usando o comando
python /path/to/tensorflow/tensorflow/python/tools/inspect_checkpoint.py --file_name=/path/to/pretrained_model/model.ckpt
O script inspect_checkpoint.py pode ser encontrado na pasta './tensorflow/python/tools' da fonte do Tensorflow.
Para especificar o mapeamento, você pode usar o meu Tensorflow-Worklab , que contém um conjunto de classes e scripts para treinar e treinar novamente modelos diferentes. Inclui um exemplo de reciclagem de modelos ResNet, localizado aqui
all_variables()
agora está obsoleto
Aqui está minha solução simples para os dois casos básicos que diferem se você deseja carregar o gráfico do arquivo ou compilá-lo durante o tempo de execução.
Esta resposta vale para o Tensorflow 0.12+ (incluindo 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
Ao usar esta técnica, verifique se todas as suas camadas / variáveis definiram explicitamente nomes exclusivos.Caso contrário, o Tensorflow tornará os nomes únicos e eles serão diferentes dos nomes armazenados no arquivo. Não é um problema na técnica anterior, porque os nomes são "mutilados" da mesma maneira no carregamento e no salvamento.
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
variável e as médias móveis da normalização do lote são variáveis não treináveis, mas ambas definitivamente valem a pena ser salvas. Além disso, você deve distinguir mais claramente a construção do gráfico da execução da sessão, por exemplo Saver(...).save()
, criará novos nós sempre que você o executar. Provavelmente não é o que você quer. E há mais ...: /
Você também pode conferir exemplos no TensorFlow / skflow , que oferece métodos save
e restore
métodos que podem ajudá-lo a gerenciar facilmente seus modelos. Possui parâmetros que você também pode controlar com que frequência deseja fazer backup do seu modelo.
Se você usar tf.train.MonitoredTrainingSession como a sessão padrão, não precisará adicionar código extra para salvar / restaurar as coisas. Basta passar um nome de dir de ponto de verificação para o construtor MonitoredTrainingSession, ele usará ganchos de sessão para lidar com eles.
Todas as respostas aqui são ótimas, mas quero acrescentar duas coisas.
Primeiro, para elaborar a resposta de @ user7505159, o "./" pode ser importante para adicionar ao início do nome do arquivo que você está restaurando.
Por exemplo, você pode salvar um gráfico sem "./" no nome do arquivo, assim:
# 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)
Mas, para restaurar o gráfico, você pode precisar acrescentar um "./" ao nome do arquivo:
# 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)
Você nem sempre precisará do "./", mas isso pode causar problemas dependendo do ambiente e da versão do TensorFlow.
Também é necessário mencionar que isso sess.run(tf.global_variables_initializer())
pode ser importante antes de restaurar a sessão.
Se você estiver recebendo um erro sobre variáveis não inicializadas ao tentar restaurar uma sessão salva, inclua sess.run(tf.global_variables_initializer())
antes da saver.restore(sess, save_file)
linha. Pode poupar uma dor de cabeça.
De acordo com a nova versão do Tensorflow, tf.train.Checkpoint
é a maneira preferível de salvar e restaurar um modelo:
Checkpoint.save
eCheckpoint.restore
escreva e leia pontos de verificação baseados em objeto, em contraste com tf.train.Saver, que grava e lê pontos de verificação baseados em variável.nome. O ponto de verificação baseado em objeto salva um gráfico de dependências entre objetos Python (Camadas, Otimizadores, Variáveis, etc.) com arestas nomeadas, e esse gráfico é usado para corresponder variáveis ao restaurar um ponto de verificação. Ele pode ser mais robusto às alterações no programa Python e ajuda a oferecer suporte à restauração na criação de variáveis ao executar com entusiasmo. Prefiratf.train.Checkpoint
sobretf.train.Saver
para o novo código .
Aqui está um exemplo:
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)
Para o tensorflow 2.0 , é tão simples quanto
# Save the model model.save('path_to_my_model.h5')
Restaurar:
new_model = tensorflow.keras.models.load_model('path_to_my_model.h5')
TF2.0
Vejo ótimas respostas para salvar modelos usando o TF1.x. Quero fornecer mais alguns indicadores para salvartensorflow.keras
modelos, o que é um pouco complicado, pois há muitas maneiras de salvar um modelo.
Aqui estou fornecendo um exemplo de salvar um tensorflow.keras
modelo na model_path
pasta no diretório atual. Isso funciona bem com o fluxo tensor mais recente (TF2.0). Atualizarei esta descrição se houver alguma alteração no futuro próximo.
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))
Se você estiver interessado em salvar apenas pesos do modelo e depois carregar pesos para restaurar o modelo,
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})
Quando temos operações personalizadas, como no caso a seguir ( tf.tile
), precisamos criar uma função e agrupar com uma camada Lambda. Caso contrário, o modelo não pode ser salvo.
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")
Acho que abordei algumas das muitas maneiras de salvar o modelo tf.keras. No entanto, existem muitas outras maneiras. Comente abaixo se o seu caso de uso não estiver coberto acima. Obrigado!
Você pode salvar as variáveis na rede usando
saver = tf.train.Saver()
saver.save(sess, 'path of save/fileName.ckpt')
Para restaurar a rede para reutilização mais tarde ou em outro script, use:
saver = tf.train.Saver()
saver.restore(sess, tf.train.latest_checkpoint('path of save/')
sess.run(....)
Pontos importantes:
sess
deve ser o mesmo entre as execuções iniciais e posteriores (estrutura coerente). saver.restore
precisa do caminho da pasta dos arquivos salvos, não de um caminho de arquivo individual. Onde você quiser salvar o modelo,
self.saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
...
self.saver.save(sess, filename)
Certifique-se de que todos os seus tf.Variable
nomes tenham nomes, pois você poderá restaurá-los posteriormente usando os nomes deles. E onde você deseja prever,
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
Verifique se a proteção é executada dentro da sessão correspondente. Lembre-se de que, se você usar o tf.train.latest_checkpoint('./')
, apenas o ponto de verificação mais recente será usado.
Para tensorflow-2.0
é muito simples.
import tensorflow as tf
model.save("model_name")
model = tf.keras.models.load_model('model_name')
Seguindo a resposta de @Vishnuvardhan Janapati, aqui está outra maneira de salvar e recarregar o modelo com camada / métrica / perda personalizada no 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})
Dessa forma, depois de executar esses códigos e salvar seu modelo com tf.keras.models.save_model
ou model.save
ou com ModelCheckpoint
retorno de chamada, você poderá recarregar seu modelo sem a necessidade de objetos personalizados precisos, tão simples quanto
new_model = tf.keras.models.load_model("./model.h5"})
Na nova versão do tensorflow 2.0, o processo de salvar / carregar um modelo é muito mais fácil. Por causa da implementação da API Keras, uma API de alto nível para o TensorFlow.
Para salvar um modelo: Verifique a documentação para referência: 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)
Para carregar um modelo:
https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/models/load_model
model = tf.keras.models.load_model(filepath)
Aqui está um exemplo simples usando o formato SavedModel do Tensorflow 2.0 (que é o formato recomendado, de acordo com a documentação ) para um classificador de conjunto de dados MNIST simples, usando a API funcional Keras sem muita imaginação:
# 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
O que é serving_default
?
É o nome da definição de assinatura da tag que você selecionou (nesse caso, a serve
tag padrão foi selecionada). Além disso, aqui explica como encontrar as tags e assinaturas de um modelo usando saved_model_cli
.
Isenções de responsabilidade
Este é apenas um exemplo básico, se você deseja colocá-lo em funcionamento, mas não é de modo algum uma resposta completa - talvez eu possa atualizá-lo no futuro. Eu só queria dar um exemplo simples usando oSavedModel
TF 2.0, porque eu não vi um, mesmo assim simples, em qualquer lugar.
A resposta de @ Tom é um exemplo de SavedModel, mas não funcionará no Tensorflow 2.0, porque infelizmente existem algumas mudanças.
@ A resposta de Janishati em Vishnuvardhan diz TF 2.0, mas não é para o formato SavedModel.