Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/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.

Una vez que haya migrado su modelo desde los grafos y sesiones de TensorFlow 1 a las APIs de TensorFlow 2, como tf.function, tf.Module, y tf.keras.Model, puede migrar el código de guardado y carga del modelo. Este bloc de notas proporciona ejemplos de cómo se puede guardar y cargar en el formato SavedModel en TensorFlow 1 y TensorFlow 2. Este es un resumen rápido de los cambios relacionados con la API para la migración de TensorFlow 1 a TensorFlow 2:

| TensorFlow 1 | Migración a TensorFlow 2 --- | --- | --- Guardado | tf.compat.v1.saved_model.Builder
tf.compat.v1.saved_model.simple_save | tf.saved_model.save
Keras: tf.keras.models.save_model Carga | tf.compat.v1.saved_model.load | tf.saved_model.load
Keras: tf.keras.models.load_model Firmas: un conjunto de tensores de entrada
y salida que
pueden usarse para ejecutar el
| Generado usando la *.signature_def utils
(p. ej. tf.compat.v1.saved_model.predict_signature_def) | Escriba una tf.function y expórtela usando el argumento signatures
en tf.saved_model.save. Clasificación
y regresión:
tipos especiales de firma | Generado con
tf.compat.v1.saved_model.classification_signature_def,
tf.compat.v1.saved_model.regression_signature_def,
y ciertas exportaciones del Estimator. | Estos dos tipos de firma han sido eliminados de TensorFlow 2.
Si la librería que sirve requiere estos nombres de método,
tf.compat.v1.saved_model.signature_def_utils.MethodNameUpdater.

Para una explicación más detallada del mapeado, consulte la sección Cambios de TensorFlow 1 a TensorFlow 2 que aparece a continuación.

Preparación

Los ejemplos siguientes muestran cómo exportar y cargar el mismo modelo TensorFlow ficticio (definido como add_two a continuación) a un formato SavedModel usando las APIs TensorFlow 1 y TensorFlow 2. Comience por establecer las importaciones y las funciones de utilidad:

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: Guardar y exportar un SavedModel

En TensorFlow 1, usted usa las APIs tf.compat.v1.saved_model.Builder, tf.compat.v1.saved_model.simple_save, y tf.estimator.Estimator.export_saved_model para construir, guardar y exportar el grafo y la sesión de TensorFlow:

1. Guarde el grafo como SavedModel con 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. Construya un 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 el grafo de inferencia del estimador como SavedModel

En la definición del model_fn Estimator (definido a continuación), puede definir firmas en su modelo devolviendo export_outputs en el tf.estimator.EstimatorSpec. Existen diferentes tipos de salidas:

  • tf.estimator.export.ClassificationOutput

  • tf.estimator.export.RegressionOutput

  • tf.estimator.export.PredictOutput

Éstas producirán tipos de firmas de clasificación, regresión y predicción, respectivamente.

Cuando se exporta el estimador con tf.estimator.Estimator.export_saved_model, estas firmas se guardarán con el 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: Guardar y exportar un SavedModel

Guardar y exportar un SavedModel definido con tf.Module

Para exportar su modelo en TensorFlow 2, debe definir un tf.Module o un tf.keras.Model que contenga todas las variables y funciones de su modelo. Luego, puede llamar a tf.saved_model.save para crear un SavedModel. Consulte la sección Guardar un modelo personalizado de la guía Utilizar el formato SavedModel para obtener más información.

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

Guardar y exportar un SavedModel definido con Keras

Obsoleto: Para los objetos Keras, se recomienda usar el nuevo formato de alto nivel .keras y tf.keras.Model.export, como se demuestra en la guía aquí. El formato SavedModel de bajo nivel sigue siendo compatible con el código existente.

Las APIs de Keras para guardar y exportar (Model.save o tf.keras.models.save_model) pueden exportar un SavedModel desde un tf.keras.Model. Consulte Guardar y cargar modelos Keras para más detalles.

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

Cargar un SavedModel

Un SavedModel guardado con cualquiera de las APIs anteriores puede ser cargado usando las APIs de TensorFlow 1 o TensorFlow 2.

Un SavedModel de TensorFlow 1 puede usarse generalmente para la inferencia cuando se carga en TensorFlow 2, pero el entrenamiento (generación de gradientes) sólo es posible si el SavedModel contiene variables de referencia. Puede verificar el dtype de las variables: si el dtype de la variable contiene "_ref", entonces es una variable de referencia.

Un SavedModel de TensorFlow 2 puede cargarse y ejecutarse desde TensorFlow 1 siempre que el SavedModel se guarde con firmas.

Las secciones siguientes contienen ejemplos de código que muestran cómo cargar los SavedModels guardados en las secciones anteriores y llamar a la firma exportada.

TensorFlow 1: Cargar un SavedModel con tf.saved_model.load

En TensorFlow 1, puede importar un SavedModel directamente en el grafo y la sesión actuales usando tf.saved_model.load. Puede llamar a Session.run en los nombres de entrada y salida del 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: Cargar un modelo guardado con tf.saved_model

En TensorFlow 2, los objetos se cargan en un objeto Python que almacena las variables y funciones. Esto es compatible con los modelos guardados de TensorFlow 1.

Consulte los documentos de la API tf.saved_model.load y Cargar y usar un modelo personalizado de la guía Usar el formato SavedModel para más detalles.

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.)

Los modelos guardados con la API TensorFlow 2 también pueden acceder a funciones tf.function y variables que se adjuntan al modelo (en lugar de las exportadas como firmas). Por ejemplo:

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

TensorFlow 2: Cargar un modelo guardado con Keras

Obsoleto: Para los objetos Keras, se recomienda usar el nuevo formato de alto nivel .keras y tf.keras.Model.export, como se demuestra en la guía aquí. El formato SavedModel de bajo nivel sigue siendo compatible con el código existente.

La API de carga de Keras (tf.keras.models.load_model) le permite volver a cargar un modelo guardado en un objeto Modelo de Keras. Tenga en cuenta que esto sólo le permite cargar SavedModels guardados con Keras (Model.save o tf.keras.models.save_model).

Los modelos guardados con tf.saved_model.save deben cargarse con tf.saved_model.load. Puede cargar un modelo Keras guardado con Model.save usando tf.saved_model.load pero sólo obtendrá el grafo de TensorFlow. Consulte la documentación de la API tf.keras.models.load_model y Guardar y cargar modelos Keras para más detalles.

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

GraphDef y MetaGraphDef

<a name="graphdef_and_metagraphdef">

No existe una forma directa de cargar un GraphDef o MetaGraphDef sin procesar en TF2. Sin embargo, puede convertir el código TF1 que importa el grafo en una concrete_function TF2 usando v1.wrap_function.

Primero, guarde un 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 las API del TF1, puede usar tf1.train.import_meta_graph para importar el grafo y restaurar los 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}))

No existen APIs de TF2 para cargar el grafo, pero puede importarlo en una función concreta que pueda ejecutarse en 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.

Cambios de TensorFlow 1 a TensorFlow 2

<a id="changes_from_tf1_to_tf2">

Esta sección enumera los términos clave de guardado y carga de TensorFlow 1, sus equivalentes en TensorFlow 2 y lo que ha cambiado.

SavedModel

SavedModel es un formato que almacena un programa TensorFlow completo con parámetros y computación. Contiene firmas usadas por plataformas servidoras para ejecutar el modelo.

El formato del archivo en sí no ha cambiado significativamente, por lo que los SavedModels pueden ser cargados y servidos usando tanto la API de TensorFlow 1 como la de TensorFlow 2.

Diferencias entre TensorFlow 1 y TensorFlow 2

Los casos de uso de servir e inferencia no se han actualizado en TensorFlow 2, aparte de los cambios en la API: se ha introducido una mejora en su capacidad para reutilizar y erscribir modelos cargados desde SavedModel.

En TensorFlow 2, el programa está representado por objetos como tf.Variable, tf.Module, o modelos Keras de nivel superior (tf.keras.Model) y capas (tf.keras.layers). Ya no hay variables globales que tengan valores almacenados en una sesión, y el grafo existe ahora en diferentes tf.functions. En consecuencia, durante la exportación de un modelo, SavedModel guarda los grafos de cada componente y función por separado.

Cuando usted escribe un programa TensorFlow con las APIs Python de TensorFlow, debe construir un objeto para administrar las variables, funciones y otros recursos. Generalmente, esto se consigue usando las APIs de Keras, pero también puede construir el objeto creando o subclasificando tf.Module.

Los modelos Keras (tf.keras.Model) y tf.Module realizan un seguimiento automático de las variables y funciones vinculadas a ellos. SavedModel guarda estas conexiones entre módulos, variables y funciones, para que puedan ser restauradas al cargar.

Firmas

Las firmas son los puntos finales de un SavedModel: indican al usuario cómo ejecutar el modelo y qué entradas necesita.

En TensorFlow 1, las firmas se crean enumerando los tensores de entrada y salida. En TensorFlow 2, las firmas se generan pasando funciones concretas (lea más sobre las funciones TensorFlow en la guía Introducción a los grafos y tf.function, en particular en la sección Polimorfismo: una Función, muchos grafos). En resumen, se genera una función concreta a partir de una 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

En TensorFlow 1, se podía llamar a Session.run con el grafo importado siempre que se conocieran los nombres de los tensores. Esto le permite recuperar los valores de las variables restauradas, o ejecutar partes del modelo que no se exportaron en las firmas.

En TensorFlow 2, puede acceder directamente a una variable, como una matriz de ponderaciones (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

o llamar a tf.functions adjuntas al objeto modelo: por ejemplo, loaded.__call__.

A diferencia del TF1, no hay forma de extraer partes de una función y acceder a valores intermedios. Usted debe exportar toda la funcionalidad necesaria en el objeto guardado.

Notas sobre la migración a TensorFlow Serving

SavedModel fue creado originalmente para trabajar con TensorFlow Serving. Esta plataforma ofrece diferentes tipos de solicitudes de predicción: clasificar, hacer regresión y predecir.

La API TensorFlow 1 le permite crear este tipo de firmas con las utilerías:

  • tf.compat.v1.saved_model.classification_signature_def

  • tf.compat.v1.saved_model.regression_signature_def

  • tf.compat.v1.saved_model.predict_signature_def

La clasificación (classification_signature_def) y la regresión (regression_signature_def) restringen las entradas y salidas, de modo que las entradas deben ser un tf.Example, y las salidas deben ser classes, scores o prediction. Por su parte, la firma de predicción (predict_signature_def) no tiene restricciones.

Los SavedModels exportados con la API TensorFlow 2 son compatibles con TensorFlow Serving, pero sólo contendrán firmas de predicción. Se han eliminado las firmas de clasificación y regresión.

Si necesita usar las firmas de clasificación y regresión, puede modificar el SavedModel exportado utilizando tf.compat.v1.saved_model.signature_def_utils.MethodNameUpdater.

Siguientes pasos

Para saber más sobre SavedModels en TensorFlow 2, consulte las siguientes guías:

Si está usando TensorFlow Hub, estas guías pueden resultarle útiles: