Usando el formato SavedModel

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

A SavedModel contiene un programa TensorFlow completa, incluyendo parámetros formados (es decir, tf.Variable s) y cálculo. No se requiere el código de construcción modelo original a plazo, lo que lo hace útil para compartir o desplegar con TFLite , TensorFlow.js , TensorFlow Sirviendo o TensorFlow Hub .

Puede guardar y cargar un modelo en formato SavedModel utilizando las siguientes API:

Creación de un modelo guardado a partir de Keras

Para una introducción rápida, esta sección exporta un modelo de Keras previamente entrenado y sirve solicitudes de clasificación de imágenes con él. El resto de la guía completará los detalles y discutirá otras formas de crear modelos guardados.

import os
import tempfile

from matplotlib import pyplot as plt
import numpy as np
import tensorflow as tf

tmpdir = tempfile.mkdtemp()
2021-08-02 22:29:54.916852: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
physical_devices = tf.config.list_physical_devices('GPU')
for device in physical_devices:
  tf.config.experimental.set_memory_growth(device, True)
2021-08-02 22:29:56.119947: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcuda.so.1
2021-08-02 22:29:56.761302: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:56.762162: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-08-02 22:29:56.762198: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-08-02 22:29:56.765833: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-08-02 22:29:56.765941: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
2021-08-02 22:29:56.767035: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcufft.so.10
2021-08-02 22:29:56.767351: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcurand.so.10
2021-08-02 22:29:56.768341: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusolver.so.11
2021-08-02 22:29:56.769229: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusparse.so.11
2021-08-02 22:29:56.769401: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-08-02 22:29:56.769488: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:56.770399: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:56.771218: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
file = tf.keras.utils.get_file(
    "grace_hopper.jpg",
    "https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg")
img = tf.keras.preprocessing.image.load_img(file, target_size=[224, 224])
plt.imshow(img)
plt.axis('off')
x = tf.keras.preprocessing.image.img_to_array(img)
x = tf.keras.applications.mobilenet.preprocess_input(
    x[tf.newaxis,...])
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg
65536/61306 [================================] - 0s 0us/step

png

Utilizará una imagen de Grace Hopper como ejemplo de ejecución y un modelo de clasificación de imágenes preentrenado de Keras, ya que es fácil de usar. Los modelos personalizados también funcionan y se tratan en detalle más adelante.

labels_path = tf.keras.utils.get_file(
    'ImageNetLabels.txt',
    'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt
16384/10484 [==============================================] - 0s 0us/step
pretrained_model = tf.keras.applications.MobileNet()
result_before_save = pretrained_model(x)

decoded = imagenet_labels[np.argsort(result_before_save)[0,::-1][:5]+1]

print("Result before saving:\n", decoded)
2021-08-02 22:29:57.268515: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-02 22:29:57.269088: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.269973: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-08-02 22:29:57.270066: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.270918: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.271716: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-08-02 22:29:57.271770: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-08-02 22:29:57.862125: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1258] Device interconnect StreamExecutor with strength 1 edge matrix:
2021-08-02 22:29:57.862160: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1264]      0 
2021-08-02 22:29:57.862168: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1277] 0:   N 
2021-08-02 22:29:57.862362: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.863344: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.864221: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-02 22:29:57.865122: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1418] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 14646 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/mobilenet/mobilenet_1_0_224_tf.h5
17227776/17225924 [==============================] - 0s 0us/step
2021-08-02 22:29:58.862423: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-08-02 22:29:59.277883: I tensorflow/stream_executor/cuda/cuda_dnn.cc:359] Loaded cuDNN version 8100
2021-08-02 22:29:59.878526: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
Result before saving:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']
2021-08-02 22:30:00.216119: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11

La predicción más alta para esta imagen es "uniforme militar".

mobilenet_save_path = os.path.join(tmpdir, "mobilenet/1/")
tf.saved_model.save(pretrained_model, mobilenet_save_path)
2021-08-02 22:30:04.194597: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:tensorflow:FOR KERAS USERS: The object that you are saving contains one or more Keras models or layers. If you are loading the SavedModel with `tf.keras.models.load_model`, continue reading (otherwise, you may ignore the following instructions). Please change your code to save with `tf.keras.models.save_model` or `model.save`, and confirm that the file "keras.metadata" exists in the export directory. In the future, Keras will only load the SavedModels that have this file. In other words, `tf.saved_model.save` will no longer write SavedModels that can be recovered as Keras models (this will apply in TF 2.5).

FOR DEVS: If you are overwriting _tracking_metadata in your class, this property has been used to save metadata in the SavedModel. The metadta field will be deprecated soon, so please move the metadata to a different file.
INFO:tensorflow:Assets written to: /tmp/tmpoijnvh4d/mobilenet/1/assets

La trayectoria de ahorro sigue una convención utilizada por TensorFlow Sirviendo donde el último componente de la ruta ( 1/ aquí) es un número de versión de su modelo - que permite a herramientas como Tensorflow Sirviendo a la razón por la frescura relativa.

Puede cargar la parte posterior SavedModel en Python con tf.saved_model.load y ver cómo se clasifica la imagen de Hopper.

loaded = tf.saved_model.load(mobilenet_save_path)
print(list(loaded.signatures.keys()))  # ["serving_default"]
['serving_default']

Las firmas importadas siempre devuelven diccionarios. Para personalizar los nombres de firmas y claves de diccionario de salida, consulte Especificación de firmas durante la exportación .

infer = loaded.signatures["serving_default"]
print(infer.structured_outputs)
{'predictions': TensorSpec(shape=(None, 1000), dtype=tf.float32, name='predictions')}

Ejecutar inferencia desde el modelo guardado da el mismo resultado que el modelo original.

labeling = infer(tf.constant(x))[pretrained_model.output_names[0]]

decoded = imagenet_labels[np.argsort(labeling)[0,::-1][:5]+1]

print("Result after saving and loading:\n", decoded)
2021-08-02 22:30:12.094694: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
2021-08-02 22:30:12.106524: I tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2000194999 Hz
Result after saving and loading:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

Ejecutar un modelo guardado en la publicación de TensorFlow

Los modelos guardados se pueden utilizar desde Python (más sobre eso a continuación), pero los entornos de producción suelen utilizar un servicio dedicado para la inferencia sin ejecutar código Python. Esto es fácil de configurar desde un modelo guardado usando TensorFlow Serving.

Ver la TensorFlow Sirviendo REST tutorial para un ejemplo tensorflow-porción de extremo a extremo.

El formato de modelo guardado en el disco

Un modelo guardado es un directorio que contiene firmas serializadas y el estado necesario para ejecutarlas, incluidos los valores de las variables y los vocabularios.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

Los saved_model.pb archivo almacena el programa real TensorFlow, o modelo, y un conjunto de firmas con nombre, cada una identificación de una función que acepta entradas de tensor y produce salidas tensor.

SavedModels puede contener múltiples variantes del modelo (múltiples v1.MetaGraphDefs , identificado con el --tag_set bandera para saved_model_cli ), pero esto es raro. APIs que crean múltiples variantes de un modelo incluyen tf.Estimator.experimental_export_all_saved_models y en TensorFlow 1.x tf.saved_model.Builder .

saved_model_cli show --dir {mobilenet_save_path} --tag_set serve
2021-08-02 22:30:12.985046: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
SignatureDef key: "__saved_model_init_op"
SignatureDef key: "serving_default"

El variables directorio contiene un puesto de control de formación estándar (ver la guía de los puestos de control de formación ).

ls {mobilenet_save_path}/variables
variables.data-00000-of-00001  variables.index

La assets directorio contiene archivos utilizados por el gráfico TensorFlow, por ejemplo archivos de texto que se utilizan para inicializar las tablas de vocabulario. No se utiliza en este ejemplo.

SavedModels pueden tener un assets.extra directorio para los archivos no utilizados por el gráfico TensorFlow, por ejemplo, información para los consumidores sobre qué hacer con el SavedModel. El propio TensorFlow no usa este directorio.

Guardar un modelo personalizado

tf.saved_model.save permite guardar tf.Module objetos y sus subclases, como tf.keras.Layer y tf.keras.Model .

Echemos un vistazo a un ejemplo de guardar y restaurar un tf.Module .

class CustomModule(tf.Module):

  def __init__(self):
    super(CustomModule, self).__init__()
    self.v = tf.Variable(1.)

  @tf.function
  def __call__(self, x):
    print('Tracing with', x)
    return x * self.v

  @tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
  def mutate(self, new_v):
    self.v.assign(new_v)

module = CustomModule()

Al guardar un tf.Module , cualquier tf.Variable atributos, tf.function -decorated métodos y tf.Module s encontrado a través de recorrido recursivo se guardan. (Vea el tutorial de Checkpoint para más información sobre este recorrido recursivo.) Sin embargo, cualquier atributo de Python, funciones, y se pierden los datos. Esto significa que cuando un tf.function se guarda, no hay código Python se guarda.

Si no se guarda ningún código Python, ¿cómo sabe SavedModel cómo restaurar la función?

Brevemente, tf.function funciona trazando el código Python para generar una ConcreteFunction (una envoltura exigible alrededor tf.Graph ). Al guardar un tf.function , en realidad está ahorrando el tf.function caché 's de ConcreteFunctions.

Para obtener más información sobre la relación entre tf.function y ConcreteFunctions, consulte la guía tf.function .

module_no_signatures_path = os.path.join(tmpdir, 'module_no_signatures')
module(tf.constant(0.))
print('Saving model...')
tf.saved_model.save(module, module_no_signatures_path)
Tracing with Tensor("x:0", shape=(), dtype=float32)
Saving model...
Tracing with Tensor("x:0", shape=(), dtype=float32)
INFO:tensorflow:Assets written to: /tmp/tmpoijnvh4d/module_no_signatures/assets

Carga y uso de un modelo personalizado

Cuando se carga un SavedModel en Python, todos tf.Variable atributos, tf.function -decorated métodos y tf.Module s se restauran en la misma estructura del objeto que el original guardado tf.Module .

imported = tf.saved_model.load(module_no_signatures_path)
assert imported(tf.constant(3.)).numpy() == 3
imported.mutate(tf.constant(2.))
assert imported(tf.constant(3.)).numpy() == 6

Debido a que ningún código Python se guarda, llamar a un tf.function con una nueva firma de entrada fallará:

imported(tf.constant([3.]))
ValueError: Could not find matching function to call for canonicalized inputs ((,), {}). Only existing signatures are [((TensorSpec(shape=(), dtype=tf.float32, name=u'x'),), {})].

Ajuste fino básico

Los objetos variables están disponibles y puede retroceder a través de funciones importadas. Eso es suficiente para ajustar (es decir, volver a entrenar) un modelo guardado en casos simples.

optimizer = tf.optimizers.SGD(0.05)

def train_step():
  with tf.GradientTape() as tape:
    loss = (10. - imported(tf.constant(2.))) ** 2
  variables = tape.watched_variables()
  grads = tape.gradient(loss, variables)
  optimizer.apply_gradients(zip(grads, variables))
  return loss
for _ in range(10):
  # "v" approaches 5, "loss" approaches 0
  print("loss={:.2f} v={:.2f}".format(train_step(), imported.v.numpy()))
loss=36.00 v=3.20
loss=12.96 v=3.92
loss=4.67 v=4.35
loss=1.68 v=4.61
loss=0.60 v=4.77
loss=0.22 v=4.86
loss=0.08 v=4.92
loss=0.03 v=4.95
loss=0.01 v=4.97
loss=0.00 v=4.98

Ajuste fino general

Un SavedModel de Keras proporciona más detalles de una llanura __call__ para hacer frente a los casos más avanzados de puesta a punto. TensorFlow Hub recomienda proporcionar lo siguiente, si corresponde, en SavedModels compartidos con el fin de ajustar:

  • Si los usos modelo de deserción u otra técnica en la que los difiere pase hacia adelante entre la formación y la inferencia (como la normalización de lotes), el __call__ método toma una, opcional con valores de Python training= argumento de que por defecto es False , pero se pueden establecer en True .
  • Al lado de la __call__ atributo, hay .variable y .trainable_variable atributos con las correspondientes listas de variables. Una variable que fue originalmente entrenable, pero está destinado a ser congelado durante la puesta a punto se omite de .trainable_variables .
  • En aras de marcos como Keras que representan regularizers peso como atributos de capas o sub-modelos, también puede haber un .regularization_losses atributo. Contiene una lista de funciones de argumento cero cuyos valores se deben sumar a la pérdida total.

Volviendo al ejemplo inicial de MobileNet, puede ver algunos de ellos en acción:

loaded = tf.saved_model.load(mobilenet_save_path)
print("MobileNet has {} trainable variables: {}, ...".format(
          len(loaded.trainable_variables),
          ", ".join([v.name for v in loaded.trainable_variables[:5]])))
MobileNet has 83 trainable variables: conv1/kernel:0, conv1_bn/gamma:0, conv1_bn/beta:0, conv_dw_1/depthwise_kernel:0, conv_dw_1_bn/gamma:0, ...
trainable_variable_ids = {id(v) for v in loaded.trainable_variables}
non_trainable_variables = [v for v in loaded.variables
                           if id(v) not in trainable_variable_ids]
print("MobileNet also has {} non-trainable variables: {}, ...".format(
          len(non_trainable_variables),
          ", ".join([v.name for v in non_trainable_variables[:3]])))
MobileNet also has 54 non-trainable variables: conv1_bn/moving_mean:0, conv1_bn/moving_variance:0, conv_dw_1_bn/moving_mean:0, ...

Especificar firmas durante la exportación

Herramientas como TensorFlow Sirviendo y saved_model_cli pueden interactuar con SavedModels. Para ayudar a estas herramientas a determinar qué ConcreteFunctions utilizar, debe especificar las firmas de servicio. tf.keras.Model s especifique automáticamente la publicación de firmas, pero usted tendrá que declarar explícitamente una firma que sirve para nuestros módulos personalizados.

Por defecto, no hay firmas se declaran en una costumbre tf.Module .

assert len(imported.signatures) == 0

Para declarar una firma de servir, especificar un ConcreteFunction utilizando la signatures kwarg. Al especificar una única firma, la clave de firma será 'serving_default' , que se guarda como la constante tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY .

module_with_signature_path = os.path.join(tmpdir, 'module_with_signature')
call = module.__call__.get_concrete_function(tf.TensorSpec(None, tf.float32))
tf.saved_model.save(module, module_with_signature_path, signatures=call)
Tracing with Tensor("x:0", dtype=float32)
Tracing with Tensor("x:0", dtype=float32)
INFO:tensorflow:Assets written to: /tmp/tmpoijnvh4d/module_with_signature/assets
imported_with_signatures = tf.saved_model.load(module_with_signature_path)
list(imported_with_signatures.signatures.keys())
['serving_default']

Para exportar varias firmas, pase un diccionario de claves de firma a ConcreteFunctions. Cada clave de firma corresponde a una función concreta.

module_multiple_signatures_path = os.path.join(tmpdir, 'module_with_multiple_signatures')
signatures = {"serving_default": call,
              "array_input": module.__call__.get_concrete_function(tf.TensorSpec([None], tf.float32))}

tf.saved_model.save(module, module_multiple_signatures_path, signatures=signatures)
Tracing with Tensor("x:0", shape=(None,), dtype=float32)
Tracing with Tensor("x:0", shape=(None,), dtype=float32)
INFO:tensorflow:Assets written to: /tmp/tmpoijnvh4d/module_with_multiple_signatures/assets
imported_with_multiple_signatures = tf.saved_model.load(module_multiple_signatures_path)
list(imported_with_multiple_signatures.signatures.keys())
['serving_default', 'array_input']

Por defecto, los nombres de tensor de salida son bastante genérico, como output_0 . Para controlar los nombres de salidas, modifique su tf.function para devolver un diccionario que mapea nombres de salida a las salidas. Los nombres de las entradas se derivan de los nombres arg de la función Python.

class CustomModuleWithOutputName(tf.Module):
  def __init__(self):
    super(CustomModuleWithOutputName, self).__init__()
    self.v = tf.Variable(1.)

  @tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
  def __call__(self, x):
    return {'custom_output_name': x * self.v}

module_output = CustomModuleWithOutputName()
call_output = module_output.__call__.get_concrete_function(tf.TensorSpec(None, tf.float32))
module_output_path = os.path.join(tmpdir, 'module_with_output_name')
tf.saved_model.save(module_output, module_output_path,
                    signatures={'serving_default': call_output})
INFO:tensorflow:Assets written to: /tmp/tmpoijnvh4d/module_with_output_name/assets
imported_with_output_name = tf.saved_model.load(module_output_path)
imported_with_output_name.signatures['serving_default'].structured_outputs
{'custom_output_name': TensorSpec(shape=(), dtype=tf.float32, name='custom_output_name')}

Cargar un modelo guardado en C ++

La versión de C ++ de la SavedModel loader proporciona una API para cargar un SavedModel desde una ruta, al tiempo que permite SessionOptions y RunOptions. Debe especificar las etiquetas asociadas con el gráfico que se cargará. La versión cargada de SavedModel se conoce como SavedModelBundle y contiene MetaGraphDef y la sesión dentro de la cual se carga.

const string export_dir = ...
SavedModelBundle bundle;
...
LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain},
               &bundle);

Detalles de la interfaz de línea de comandos del modelo guardado

Puede utilizar la interfaz de línea de comandos (CLI) del modelo guardado para inspeccionar y ejecutar un modelo guardado. Por ejemplo, puede utilizar la CLI para inspeccionar el modelo de SignatureDef s. La CLI le permite confirmar rápidamente que el tipo y la forma del tensor de entrada coinciden con el modelo. Además, si desea probar su modelo, puede usar la CLI para hacer una verificación de cordura pasando entradas de muestra en varios formatos (por ejemplo, expresiones de Python) y luego recuperando la salida.

Instalar la CLI de SavedModel

En términos generales, puede instalar TensorFlow de cualquiera de las dos formas siguientes:

  • Instalando un binario de TensorFlow prediseñado.
  • Compilando TensorFlow a partir del código fuente.

Si ha instalado TensorFlow través de un binario TensorFlow pre-construidos, entonces el SavedModel CLI ya está instalado en su sistema en ruta bin/saved_model_cli .

Si usted construyó TensorFlow desde el código fuente, debe ejecutar el siguiente comando adicional para construir saved_model_cli :

$ bazel build tensorflow/python/tools:saved_model_cli

Resumen de comandos

La CLI SavedModel admite los dos comandos siguientes en un modelo guardado:

  • show , que muestra los cálculos disponible de una SavedModel.
  • run , que se ejecuta un cálculo de una SavedModel.

show de comandos

A SavedModel contiene una o más variantes de modelo (técnicamente, v1.MetaGraphDef s), identificado por su etiqueta de conjuntos. Para servir un modelo, puede que se pregunte qué tipo de SignatureDef s son en cada variante del modelo, y cuáles son sus entradas y salidas. El show de comandos permiten examinar el contenido de la SavedModel en orden jerárquico. Esta es la sintaxis:

usage: saved_model_cli show [-h] --dir DIR [--all]
[--tag_set TAG_SET] [--signature_def SIGNATURE_DEF_KEY]

Por ejemplo, el siguiente comando muestra todos los conjuntos de etiquetas disponibles en el modelo guardado:

$ saved_model_cli show --dir /tmp/saved_model_dir
The given SavedModel contains the following tag-sets:
serve
serve, gpu

El siguiente comando muestra todos disponibles SignatureDef claves para un conjunto de etiquetas:

$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve
The given SavedModel `MetaGraphDef` contains `SignatureDefs` with the
following keys:
SignatureDef key: "classify_x2_to_y3"
SignatureDef key: "classify_x_to_y"
SignatureDef key: "regress_x2_to_y3"
SignatureDef key: "regress_x_to_y"
SignatureDef key: "regress_x_to_y2"
SignatureDef key: "serving_default"

Si hay múltiples etiquetas en la etiqueta-set, debe especificar todas las etiquetas, cada etiqueta separada por una coma. Por ejemplo:

$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve,gpu

Para mostrar todas las entradas y salidas TensorInfo para una específica SignatureDef , pasar en el SignatureDef clave para signature_def opción. Esto es muy útil cuando desea conocer el valor de la clave del tensor, el tipo d y la forma de los tensores de entrada para ejecutar el gráfico de cálculo más tarde. Por ejemplo:

$ saved_model_cli show --dir \
/tmp/saved_model_dir --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):
  inputs['x'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: x:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['y'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: y:0
Method name is: tensorflow/serving/predict

Para mostrar toda la información disponible en el SavedModel, utilice el --all opción. Por ejemplo:

$ saved_model_cli show --dir /tmp/saved_model_dir --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['classify_x2_to_y3']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: x2:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['scores'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: y3:0
  Method name is: tensorflow/serving/classify

...

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['x'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: x:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['y'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: y:0
  Method name is: tensorflow/serving/predict

run de comandos

Invocar la run de comandos para ejecutar un cálculo gráfico, pasando entradas y, a continuación se presentan (y opcionalmente guardar) las salidas. Esta es la sintaxis:

usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_def
                           SIGNATURE_DEF_KEY [--inputs INPUTS]
                           [--input_exprs INPUT_EXPRS]
                           [--input_examples INPUT_EXAMPLES] [--outdir OUTDIR]
                           [--overwrite] [--tf_debug]

La run de comandos proporciona las siguientes tres formas de pasar las entradas al modelo:

  • --inputs opción que permite pasar ndarray numpy en los archivos.
  • --input_exprs opción le permite pasar expresiones Python.
  • --input_examples opción le permite pasar tf.train.Example .

--inputs

Para pasar los datos de entrada en los archivos, especifique el --inputs opción, que tiene el siguiente formato general:

--inputs <INPUTS>

donde los insumos es cualquiera de los siguientes formatos:

  • <input_key>=<filename>
  • <input_key>=<filename>[<variable_name>]

Es posible pasar múltiples entradas. Si lo hace pasar múltiples entradas, use un punto y coma para separar cada una de las entradas.

saved_model_cli usos numpy.load para cargar el nombre de archivo. El nombre de archivo puede estar en cualquiera de los siguientes formatos:

  • .npy
  • .npz
  • formato de pepinillo

Un .npy archivo siempre contiene una ndarray numpy. Por lo tanto, cuando se carga de un .npy archivo, el contenido será asignado directamente al tensor de entrada especificado. Si especifica un variable_name con ese .npy archivo, el variable_name tendrá en cuenta y se emitirá una advertencia.

Cuando la carga de un .npz archivo (zip), puede especificar un variable_name para identificar la variable dentro del archivo zip para cargar la clave para tensor de entrada. Si no se especifica un variable_name, la CLI SavedModel comprobará que sólo un archivo se incluye en el archivo zip y cargarlo para la llave tensor de entrada especificado.

Cuando la carga de un archivo de salmuera, si no hay variable_name se especifica en los corchetes, sea lo que sea dentro del archivo de la salmuera se pasará a la llave tensor de entrada especificado. De lo contrario, el SavedModel CLI asumirá un diccionario se almacena en el archivo de salmuera y se utilizará el valor que corresponde a la variable_name.

--input_exprs

Para pasar a través de las entradas expresiones Python, especificar el --input_exprs opción. Esto puede ser útil para cuando usted no tiene archivos de datos por ahí, pero todavía quiere a la cordura comprobar el modelo con algunas entradas simples que coinciden con el dtype y la forma del modelo de la SignatureDef s. Por ejemplo:

`<input_key>=[[1],[2],[3]]`

Además de las expresiones de Python, también puede pasar numerosas funciones. Por ejemplo:

`<input_key>=np.ones((32,32,3))`

(Nota que el numpy módulo ya está disponible para usted como np ).

--input_examples

Para pasar tf.train.Example como entradas, especificar el --input_examples opción. Para cada tecla de entrada, se necesita una lista de diccionario, donde cada diccionario es una instancia de tf.train.Example . Las claves del diccionario son las características y los valores son las listas de valores para cada característica. Por ejemplo:

`<input_key>=[{"age":[22,24],"education":["BS","MS"]}]`

Guardar salida

De forma predeterminada, la CLI SavedModel escribe la salida en stdout. Si un directorio se pasa a --outdir opción, las salidas se pueden guardar como .npy archivos con nombres de teclas del tensor de salida en el directorio dado.

Utilice --overwrite para sobrescribir los archivos de salida existentes.