Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/guide/migrate/saved_model.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Depois de migrar seu modelo dos grafos e sessões do TensorFlow 1 para APIs do TensorFlow 2, como tf.function, tf.Module e tf.keras.Model, você poderá migrar o código de salvamento e carregamento do modelo. Este notebook fornece exemplos de como você pode salvar e carregar o formato SavedModel no TensorFlow 1 e TensorFlow 2. Aqui está uma rápida visão geral das alterações de API relacionadas para migração do TensorFlow 1 para o TensorFlow 2:

| TensorFlow 1 | Migração para o TensorFlow 2 --- | --- | --- Salvando | tf.compat.v1.saved_model.Builder
tf.compat.v1.saved_model.simple_save | tf.saved_model.save
Keras: tf.keras.models.save_model Carregando | tf.compat.v1.saved_model.load | tf.saved_model.load
Keras: tf.keras.models.load_model Assinaturas: um conjunto de entradas
e tensores de saída que
podem ser usados para executar o
| Gerado usando os utilitários *.signature_def
(por exemplo, tf.compat.v1.saved_model.predict_signature_def) | Escreva uma tf.function e exporte-a usando o argumento signatures
em tf.saved_model.save. Classificação
e regressão:
tipos especiais de assinaturas | Gerado com
tf.compat.v1.saved_model.classification_signature_def,
tf.compat.v1.saved_model.regression_signature_def,
e determinadas exportações do Estimator. | Esses dois tipos de assinatura foram removidos do TensorFlow 2.
Se a biblioteca de serviço exigir esses nomes de métodos,
tf.compat.v1.saved_model.signature_def_utils.MethodNameUpdater.

Para uma explicação mais detalhada do mapeamento, consulte a seção Mudanças do TensorFlow 1 para o TensorFlow 2 abaixo.

Configuração

Os exemplos abaixo mostram como exportar e carregar o mesmo modelo fictício do TensorFlow (definido como add_two abaixo) para um formato SavedModel usando as APIs TensorFlow 1 e TensorFlow 2. Comece configurando as importações e funções utilitárias:

import tensorflow as tf import tensorflow.compat.v1 as tf1 import shutil def remove_dir(path): try: shutil.rmtree(path) except: pass def add_two(input): return input + 2

TensorFlow 1: salve e exporte um SavedModel

No TensorFlow 1, você usa as APIs tf.compat.v1.saved_model.Builder , tf.compat.v1.saved_model.simple_save e tf.estimator.Estimator.export_saved_model para criar, salvar e exportar o grafo e a sessão do TensorFlow:

1. Salve o gráfico como SavedModel com SavedModelBuilder

remove_dir("saved-model-builder") with tf.Graph().as_default() as g: with tf1.Session() as sess: input = tf1.placeholder(tf.float32, shape=[]) output = add_two(input) print("add two output: ", sess.run(output, {input: 3.})) # Save with SavedModelBuilder builder = tf1.saved_model.Builder('saved-model-builder') sig_def = tf1.saved_model.predict_signature_def( inputs={'input': input}, outputs={'output': output}) builder.add_meta_graph_and_variables( sess, tags=["serve"], signature_def_map={ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY: sig_def }) builder.save()
!saved_model_cli run --dir saved-model-builder --tag_set serve \ --signature_def serving_default --input_exprs input=10

2. Crie um SavedModel para servir

remove_dir("simple-save") with tf.Graph().as_default() as g: with tf1.Session() as sess: input = tf1.placeholder(tf.float32, shape=[]) output = add_two(input) print("add_two output: ", sess.run(output, {input: 3.})) tf1.saved_model.simple_save( sess, 'simple-save', inputs={'input': input}, outputs={'output': output})
!saved_model_cli run --dir simple-save --tag_set serve \ --signature_def serving_default --input_exprs input=10

3. Exporte o grafo de inferência do Estimador como um SavedModel

Na definição do Estimador model_fn (definido abaixo), você pode definir assinaturas em seu modelo retornando export_outputs em tf.estimator.EstimatorSpec. Existem diferentes tipos de saídas:

  • tf.estimator.export.ClassificationOutput

  • tf.estimator.export.RegressionOutput

  • tf.estimator.export.PredictOutput

Eles produzirão tipos de assinatura para classificação, regressão e previsão, respectivamente.

Quando o estimador for exportado com tf.estimator.Estimator.export_saved_model, essas assinaturas serão salvas com o modelo.

def model_fn(features, labels, mode): output = add_two(features['input']) step = tf1.train.get_global_step() return tf.estimator.EstimatorSpec( mode, predictions=output, train_op=step.assign_add(1), loss=tf.constant(0.), export_outputs={ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY: \ tf.estimator.export.PredictOutput({'output': output})}) est = tf.estimator.Estimator(model_fn, 'estimator-checkpoints') # Train for one step to create a checkpoint. def train_fn(): return tf.data.Dataset.from_tensors({'input': 3.}) est.train(train_fn, steps=1) # This utility function `build_raw_serving_input_receiver_fn` takes in raw # tensor features and builds an "input serving receiver function", which # creates placeholder inputs to the model. serving_input_fn = tf.estimator.export.build_raw_serving_input_receiver_fn( {'input': tf.constant(3.)}) # Pass in a dummy input batch. estimator_path = est.export_saved_model('exported-estimator', serving_input_fn) # Estimator's export_saved_model creates a time stamped directory. Move this # to a set path so it can be inspected with `saved_model_cli` in the cell below. !rm -rf estimator-model import shutil shutil.move(estimator_path, 'estimator-model')
!saved_model_cli run --dir estimator-model --tag_set serve \ --signature_def serving_default --input_exprs input=[10]

TensorFlow 2: salve e exporte um SavedModel

Salve e exporte um SavedModel definido com tf.Module

Para exportar seu modelo no TensorFlow 2, você deve definir um tf.Module ou um tf.keras.Model para armazenar todas as variáveis ​​e funções do seu modelo. Então, você pode chamar tf.saved_model.save para criar um SavedModel. Consulte a seção Salvando um modelo personalizado no guia Usando o formato SavedModel para saber mais.

class MyModel(tf.Module): @tf.function def __call__(self, input): return add_two(input) model = MyModel() @tf.function def serving_default(input): return {'output': model(input)} signature_function = serving_default.get_concrete_function( tf.TensorSpec(shape=[], dtype=tf.float32)) tf.saved_model.save( model, 'tf2-save', signatures={ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature_function})
!saved_model_cli run --dir tf2-save --tag_set serve \ --signature_def serving_default --input_exprs input=10

Salve e exporte um SavedModel definido com Keras

Obsoleto: para objetos do Keras, recomenda-se usar o novo formato de alto nível .keras e tf.keras.Model.export, conforme demonstrado neste guia. O formato de baixo nível SavedModel continua com suporte para códigos existentes.

As APIs Keras para salvar e exportar — Model.save ou tf.keras.models.save_model — podem exportar um SavedModel de um tf.keras.Model. Confira Salvando e carregando modelos Keras para obter mais detalhes.

inp = tf.keras.Input(3) out = add_two(inp) model = tf.keras.Model(inputs=inp, outputs=out) @tf.function(input_signature=[tf.TensorSpec(shape=[], dtype=tf.float32)]) def serving_default(input): return {'output': model(input)} model.save('keras-model', save_format='tf', signatures={ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY: serving_default})
!saved_model_cli run --dir keras-model --tag_set serve \ --signature_def serving_default --input_exprs input=10

Carregando um SavedModel

Um SavedModel salvo com qualquer uma das APIs acima pode ser carregado usando as APIs TensorFlow 1 ou TensorFlow 2.

Um SavedModel do TensorFlow 1 geralmente pode ser usado para inferência quando carregado no TensorFlow 2, mas o treinamento (geração de gradientes) só é possível se o SavedModel contiver variáveis ​​de características. Você pode verificar o dtype das variáveis ​​- se a variável dtype contiver "_ref", então é uma variável de referência.

Um SavedModel do TensorFlow 2 pode ser carregado e executado a partir do TensorFlow 1, desde que o SavedModel seja salvo com assinaturas.

As seções abaixo contêm exemplos de código que mostram como carregar os SavedModels salvos nas seções anteriores e chamar a assinatura exportada.

TensorFlow 1: Carregando um SavedModel com tf.saved_model.load

No TensorFlow 1, você pode importar um SavedModel diretamente para o grafo e sessão atuais usando tf.saved_model.load. Você pode chamar Session.run nos nomes de entrada e saída do tensor:

def load_tf1(path, input): print('Loading from', path) with tf.Graph().as_default() as g: with tf1.Session() as sess: meta_graph = tf1.saved_model.load(sess, ["serve"], path) sig_def = meta_graph.signature_def[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY] input_name = sig_def.inputs['input'].name output_name = sig_def.outputs['output'].name print(' Output with input', input, ': ', sess.run(output_name, feed_dict={input_name: input})) load_tf1('saved-model-builder', 5.) load_tf1('simple-save', 5.) load_tf1('estimator-model', [5.]) # Estimator's input must be batched. load_tf1('tf2-save', 5.) load_tf1('keras-model', 5.)

TensorFlow 2: Carregando um modelo salvo com tf.saved_model

No TensorFlow 2, os objetos são carregados em um objeto Python que armazena as variáveis ​​e funções. Isso é compatível com modelos salvos no TensorFlow 1.

Confira os documentos da API tf.saved_model.load e a seção Carregando e usando um modelo personalizado no guia Usando o formato SavedModel para mais detalhes.

def load_tf2(path, input): print('Loading from', path) loaded = tf.saved_model.load(path) out = loaded.signatures[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]( tf.constant(input))['output'] print(' Output with input', input, ': ', out) load_tf2('saved-model-builder', 5.) load_tf2('simple-save', 5.) load_tf2('estimator-model', [5.]) # Estimator's input must be batched. load_tf2('tf2-save', 5.) load_tf2('keras-model', 5.)

Os modelos salvos com a API do TensorFlow 2 também podem acessar objetos tf.function e variáveis ​​anexadas ao modelo (em vez daquelas exportadas como assinaturas). Por exemplo:

loaded = tf.saved_model.load('tf2-save') print('restored __call__:', loaded.__call__) print('output with input 5.', loaded(5))

TensorFlow 2: Carregando um modelo salvo com Keras

Obsoleto: para objetos do Keras, recomenda-se usar o novo formato de alto nível .keras e tf.keras.Model.export, conforme demonstrado neste guia. O formato de baixo nível SavedModel continua com suporte para códigos existentes.

A API de carregamento do Keras tf.keras.models.load_model - permite recarregar um modelo salvo de volta num objeto Keras Model. Observe que isto só permite carregar SavedModels salvos com Keras (Model.save ou tf.keras.models.save_model).

Os modelos salvos com tf.saved_model.save devem ser carregados com tf.saved_model.load. Você pode carregar um modelo Keras salvo com Model.save usando tf.saved_model.load, mas obterá apenas o grafo do TensorFlow. Consulte a documentação da API tf.keras.models.load_model e o guia Salvando e carregando modelos Keras para mais detalhes.

loaded_model = tf.keras.models.load_model('keras-model') loaded_model.predict_on_batch(tf.constant([1, 3, 4]))

GraphDef e MetaGraphDef

<a name="graphdef_and_metagraphdef">

Não existe uma maneira simples de carregar um GraphDef ou MetaGraphDef bruto no TF2. No entanto, você pode converter o código TF1 que importa o grafo numa concrete_function do TF2 usandov1.wrap_function.

Primeiro, salve um MetaGraphDef:

# Save a simple multiplication computation: with tf.Graph().as_default() as g: x = tf1.placeholder(tf.float32, shape=[], name='x') v = tf.Variable(3.0, name='v') y = tf.multiply(x, v, name='y') with tf1.Session() as sess: sess.run(v.initializer) print(sess.run(y, feed_dict={x: 5})) s = tf1.train.Saver() s.export_meta_graph('multiply.pb', as_text=True) s.save(sess, 'multiply_values.ckpt')

Usando APIs do TF1, você pode usar tf1.train.import_meta_graph para importar o grafo e restaurar os valores:

with tf.Graph().as_default() as g: meta = tf1.train.import_meta_graph('multiply.pb') x = g.get_tensor_by_name('x:0') y = g.get_tensor_by_name('y:0') with tf1.Session() as sess: meta.restore(sess, 'multiply_values.ckpt') print(sess.run(y, feed_dict={x: 5}))

Não há APIs do TF2 para carregar o grafo, mas você ainda pode importá-lo para uma função concreta que pode ser executada no modo eager:

def import_multiply(): # Any graph-building code is allowed here. tf1.train.import_meta_graph('multiply.pb') # Creates a tf.function with all the imported elements in the function graph. wrapped_import = tf1.wrap_function(import_multiply, []) import_graph = wrapped_import.graph x = import_graph.get_tensor_by_name('x:0') y = import_graph.get_tensor_by_name('y:0') # Restore the variable values. tf1.train.Saver(wrapped_import.variables).restore( sess=None, save_path='multiply_values.ckpt') # Create a concrete function by pruning the wrap_function (similar to sess.run). multiply_fn = wrapped_import.prune(feeds=x, fetches=y) # Run this function multiply_fn(tf.constant(5.)) # inputs to concrete functions must be Tensors.

Mudanças do TensorFlow 1 para o TensorFlow 2

<a id="changes_from_tf1_to_tf2">

Esta seção lista os principais termos de salvamento e carregamento do TensorFlow 1, seus equivalentes do TensorFlow 2 e o que mudou.

SavedModel

SavedModel é um formato que armazena um programa TensorFlow completo com seus parâmetros e computação. Ele contém assinaturas usadas pelas plataformas de serviço para executar o modelo.

O formato do arquivo em si não mudou significativamente, portanto, SavedModels podem ser carregados e servidos usando APIs TensorFlow 1 ou TensorFlow 2.

Diferenças entre TensorFlow 1 e TensorFlow 2

Os casos de uso serviço (serving) e inferência (inference) não foram atualizados no TensorFlow 2, além das alterações na API – a melhoria foi introduzida na capacidade de reutilizar e compor modelos carregados de SavedModel.

No TensorFlow 2, o programa é representado por objetos como tf.Variable, tf.Module ou modelos Keras de nível superior (tf.keras.Model) e camadas (tf.keras.layers). Não há mais variáveis ​​globais que tenham valores armazenados numa sessão, e o grafo agora existe em diferentes objetos tf.function. Conseqüentemente, durante uma exportação de modelo, SavedModel salva cada componente e grafo de função separadamente.

Ao escrever um programa do TensorFlow com as APIs Python do TensorFlow, você deve criar um objeto para gerenciar as variáveis, funções e outros recursos. Geralmente, isso é feito usando as APIs Keras, mas você também pode construir o objeto criando um tf.Module ou uma subclasse dele.

Os modelos Keras (tf.keras.Model) e tf.Module rastreiam automaticamente variáveis ​​e funções anexadas a eles. SavedModel salva essas conexões entre módulos, variáveis ​​e funções, para que possam ser restauradas durante o carregamento.

Assinaturas

As assinaturas são os endpoints de um SavedModel – elas informam ao usuário como executar o modelo e quais entradas são necessárias.

No TensorFlow 1, as assinaturas são criadas listando os tensores de entrada e saída. No TensorFlow 2, as assinaturas são geradas pela passagem de funções concretas. (Leia mais sobre as funções do TensorFlow no guia Introdução a grafos e tf.function, particularmente na seção Polimorfismo: uma função, muitos grafos.) Resumindo, uma função concreta é gerada a partir de um tf.function:

# Option 1: Specify an input signature. @tf.function(input_signature=[...]) def fn(...): ... return outputs tf.saved_model.save(model, path, signatures={ 'name': fn })
# Option 2: Call `get_concrete_function` @tf.function def fn(...): ... return outputs tf.saved_model.save(model, path, signatures={ 'name': fn.get_concrete_function(...) })

Session.run

No TensorFlow 1, você poderia chamar Session.run com o grafo importado, desde que já conhecesse os nomes dos tensores. Isto permite recuperar os valores de variáveis ​​restaurados ou executar partes do modelo que não foram exportadas nas assinaturas.

No TensorFlow 2, você pode acessar uma variável diretamente, como uma matriz de pesos (kernel):

model = tf.Module() model.dense_layer = tf.keras.layers.Dense(...) tf.saved_model.save('my_saved_model') loaded = tf.saved_model.load('my_saved_model') loaded.dense_layer.kernel

ou chamar tf.functions anexadas ao objeto de modelo: por exemplo, loaded.__call__.

Diferentemente do TF1, não há como extrair partes de uma função e acessar valores intermediários. Você precisa exportar todas as funcionalidades necessárias no objeto salvo.

Notas de migração do TensorFlow Serving

O SavedModel foi originalmente criado para funcionar com o TensorFlow Serving. Esta plataforma oferece diferentes tipos de solicitações de previsão: classificar (classify), regredir (regress) e prever (predict).

A API TensorFlow 1 permite criar estes tipos de assinaturas com os utilitários a seguir:

  • tf.compat.v1.saved_model.classification_signature_def

  • tf.compat.v1.saved_model.regression_signature_def

  • tf.compat.v1.saved_model.predict_signature_def

A classificação (classification_signature_def) e a regressão (regression_signature_def) restringem as entradas e saídas, portanto as entradas devem ser tf.Example e as saídas devem ser classes, scores ou prediction. Enquanto isso, a assinatura de previsão (predict_signature_def) não tem restrições.

SavedModels exportados com a API TensorFlow 2 são compatíveis com TensorFlow Serving, mas conterão apenas assinaturas de previsão. As assinaturas de classificação e regressão foram removidas.

Se precisar do uso das assinaturas de classificação e regressão, você poderá modificar o SavedModel exportado usando tf.compat.v1.saved_model.signature_def_utils.MethodNameUpdater.

Próximos passos

Para saber mais sobre SavedModels no TensorFlow 2, confira os seguintes guias:

Se você estiver usando o TensorFlow Hub, estes guias poderão ser úteis: