Verwenden des SavedModel-Formats

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

A SavedModel enthält ein komplettes TensorFlow Programm, einschließlich trainierten Parameter (dh tf.Variable s) und Berechnung. Es erfordert nicht die ursprüngliche Modell Bauordnung zu laufen, die für den Austausch oder die Bereitstellung es nützlich machen mit TFLite , TensorFlow.js , TensorFlow Serving oder TensorFlow Hub .

Sie können ein Modell im SavedModel-Format mit den folgenden APIs speichern und laden:

Erstellen eines gespeicherten Modells aus Keras

Für eine schnelle Einführung exportiert dieser Abschnitt ein vortrainiertes Keras-Modell und bedient damit Bildklassifizierungsanfragen. Der Rest des Handbuchs wird Details ausfüllen und andere Möglichkeiten zum Erstellen von SavedModels besprechen.

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

Als laufendes Beispiel verwenden Sie ein Bild von Grace Hopper und ein vortrainiertes Bildklassifizierungsmodell von Keras, da es einfach zu verwenden ist. Benutzerdefinierte Modelle funktionieren auch und werden später ausführlich behandelt.

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

Die Top-Vorhersage für dieses Bild ist "Militäruniform".

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

Der save-Pfad folgt eine Konvention von TensorFlow verwendet Serving , wo die letzten Pfadkomponente ( 1/ hier) eine Versionsnummer für Ihr Modell ist - es erlaubt Tools wie Tensorflow über die relative Frischen Grund Serving.

Sie können die SavedModel zurück in Python mit laden tf.saved_model.load und sehen , wie Admiral Hoppers Bild klassifiziert wird.

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

Importierte Signaturen geben immer Wörterbücher zurück. Um Signaturnamen und Ausgabewörterbuchschlüssel anpassen, siehe Festlegen von Unterschriften während des Exports .

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

Das Ausführen der Inferenz aus dem SavedModel liefert das gleiche Ergebnis wie das Originalmodell.

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']

Ausführen eines SavedModel in TensorFlow Serving

SavedModels können von Python aus verwendet werden (mehr dazu weiter unten), aber Produktionsumgebungen verwenden normalerweise einen dedizierten Dienst für die Inferenz, ohne Python-Code auszuführen. Dies ist mithilfe von TensorFlow Serving einfach von einem SavedModel aus einzurichten.

Siehe die TensorFlow Serving REST - Tutorial für ein End-to-End - tensorflow-Serving - Beispiel.

Das SavedModel-Format auf der Festplatte

Ein SavedModel ist ein Verzeichnis, das serialisierte Signaturen und den für deren Ausführung erforderlichen Status enthält, einschließlich Variablenwerten und Vokabularen.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

Die saved_model.pb Datei speichert das tatsächliche TensorFlow Programm oder das Modell und eine Reihe von Namen Signaturen, Identifizieren jeder eine Funktion , die Tensor - Eingänge und erzeugt Ausgänge Tensor annimmt.

SavedModels können mehrere Varianten des Modells (multiple enthalten v1.MetaGraphDefs , identifiziert mit dem --tag_set Flag auf saved_model_cli ), aber dies ist selten. APIs , die mehrere Varianten eines Modells erstellen umfassen tf.Estimator.experimental_export_all_saved_models und in 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"

Das variables Verzeichnis enthält einen Standard - Schulungs checkpoint (siehe Leitfaden für Trainingskontrollen ).

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

Das assets Verzeichnis enthält Dateien , die von der TensorFlow Grafik verwendet, zum Beispiel Textdateien verwendeten Vokabular Tabellen zu initialisieren. Es wird in diesem Beispiel nicht verwendet.

SavedModels kann eine haben assets.extra Verzeichnis für alle Dateien nicht von der TensorFlow Grafik verwendet, zum Beispiel der Information der Verbraucher über das, was mit dem SavedModel zu tun. TensorFlow selbst verwendet dieses Verzeichnis nicht.

Speichern eines benutzerdefinierten Modells

tf.saved_model.save Speichern unterstützt tf.Module Objekte und ihre Unterklassen, wie tf.keras.Layer und tf.keras.Model .

Schauen wir uns ein Beispiel des Sparens und eine Wiederherstellung 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()

Wenn Sie speichern eine tf.Module , alle tf.Variable Attribute, tf.function Methoden -Dekoriert und tf.Module s über rekursive Traversal gefunden werden gespeichert. (Siehe Checkpoint Tutorial für weitere Einzelheiten zu dieser rekursiven Traversal.) Jedoch jeder Python - Attribute, Funktionen und Daten verloren gehen. Dies bedeutet , dass , wenn ein tf.function gespeichert wird, wird kein Python - Code gespeichert.

Wenn kein Python-Code gespeichert wird, woher weiß SavedModel dann, wie die Funktion wiederhergestellt wird?

Kurz gesagt, tf.function funktioniert , indem die Python - Code Tracing ein ConcreteFunction (eine aufrufbare Wrapper um zu erzeugen tf.Graph ). Wenn eine Einsparung tf.function , du sparen Sie wirklich die tf.function ‚s Cache von ConcreteFunctions.

Um mehr zu erfahren über die Beziehung zwischen tf.function und ConcreteFunctions finden Sie in der tf.function Führung .

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

Laden und Verwenden eines benutzerdefinierten Modells

Wenn Sie eine SavedModel in Python laden, alle tf.Variable Attribute, tf.function -Dekoriert Methoden und tf.Module s sind in der gleichen Objektstruktur gestellt wie das Original gespeichert 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

Da kein Python - Code gespeichert wird, einen Aufruf tf.function wird mit einem neuen Eingang Signatur fehlschlagen:

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'),), {})].

Grundlegende Feinabstimmung

Variable Objekte sind verfügbar, und Sie können durch importierte Funktionen Backproping durchführen. Das reicht in einfachen Fällen aus, um ein SavedModel zu verfeinern (dh umzutrainieren).

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

Allgemeine Feinabstimmung

Ein SavedModel von Keras bietet mehr Details als ein einfaches __call__ fortgeschrittene Fälle der Feinabstimmung zu adressieren. TensorFlow Hub empfiehlt, gegebenenfalls die folgenden in SavedModels bereitzustellen, die zum Zwecke der Feinabstimmung freigegeben sind:

  • Wenn die Modell Verwendungen Ausfall oder eine andere Technik , bei der die Vorwärtsdurchlauf unterscheidet sich zwischen Ausbildung und Inferenz (wie Batch - Normalisierung), die __call__ nimmt Methode eine optionale, Python-wertige training= Argument , dass standardmäßig auf False aber kann eingestellt werden auf True .
  • Neben dem __call__ Attribut gibt es .variable und .trainable_variable Attribute mit den entsprechenden Listen von Variablen. Eine Variable , die ursprünglich trainierbar war aber soll bei der Feinabstimmung eingefroren werden soll , aus weggelassen .trainable_variables .
  • Aus Gründen der Frameworks wie Keras das Gewicht regularizers als Attribute von Schichten oder Untermodellen darstellen, kann es auch ein seine .regularization_losses Attribut. Es enthält eine Liste von Null-Argument-Funktionen, deren Werte zum Totalverlust addiert werden sollen.

Wenn Sie zum ersten MobileNet-Beispiel zurückkehren, können Sie einige davon in Aktion sehen:

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

Signaturen beim Export angeben

Tools wie TensorFlow Serving und saved_model_cli können mit SavedModels interagieren. Damit diese Tools bestimmen können, welche ConcreteFunctions verwendet werden sollen, müssen Sie Serving-Signaturen angeben. tf.keras.Model s angeben automatisch Signaturen dienen, aber Sie müssen explizit eine Portion Signatur für unsere eigene Module deklarieren.

Standardmäßig werden keine Signaturen in einem benutzerdefinierten erklärt tf.Module .

assert len(imported.signatures) == 0

Um eine Portion Signatur zu deklarieren, geben Sie eine ConcreteFunction die Verwendung von signatures kwarg. Wenn eine einzige Unterschrift anzugeben, wird sein Signaturschlüssel sein 'serving_default' , die als Konstante gespeichert wird 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']

Um mehrere Signaturen zu exportieren, übergeben Sie ein Wörterbuch mit Signaturschlüsseln an ConcreteFunctions. Jeder Signaturschlüssel entspricht einer ConcreteFunction.

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']

Standardmäßig sind die Ausgänge Tensor Namen ziemlich allgemein, wie output_0 . Um die Namen der Ausgänge zu steuern, ändern Sie Ihre tf.function ein Wörterbuch zurück , die Ausgangsnamen an Ausgänge abbildet. Die Namen der Eingaben werden von den Argumentnamen der Python-Funktion abgeleitet.

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')}

Laden Sie ein SavedModel in C++

Die C ++ Version des SavedModel Loader bietet eine API einen SavedModel von einem Pfad zu laden, während SessionOptions und RunOptions ermöglicht. Sie müssen die Tags angeben, die dem zu ladenden Graphen zugeordnet sind. Die geladene Version von SavedModel wird als SavedModelBundle bezeichnet und enthält die MetaGraphDef und die Sitzung, in der sie geladen wird.

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

Details der SavedModel-Befehlszeilenschnittstelle

Sie können das SavedModel Command Line Interface (CLI) verwenden, um ein SavedModel zu überprüfen und auszuführen. Zum Beispiel können Sie die CLI des Modells prüfen SignatureDef s. Mit der CLI können Sie schnell bestätigen, dass der eingegebene Tensor dtype und die Form mit dem Modell übereinstimmen. Wenn Sie Ihr Modell testen möchten, können Sie außerdem die CLI verwenden, um eine Plausibilitätsprüfung durchzuführen, indem Sie Beispieleingaben in verschiedenen Formaten (z. B. Python-Ausdrücke) übergeben und dann die Ausgabe abrufen.

Installieren Sie die SavedModel-CLI

Im Großen und Ganzen können Sie TensorFlow auf eine der folgenden zwei Arten installieren:

  • Durch die Installation einer vorgefertigten TensorFlow-Binärdatei.
  • Durch Erstellen von TensorFlow aus dem Quellcode.

Wenn Sie TensorFlow durch einen vorgefertigten TensorFlow binär installiert ist , dann wird die SavedModel CLI bereits auf Ihrem System installiert Pfadname bin/saved_model_cli .

Wenn Sie TensorFlow aus dem Quellcode gebaut, müssen Sie die folgenden zusätzlichen Befehl zu bauen laufen saved_model_cli :

$ bazel build tensorflow/python/tools:saved_model_cli

Übersicht der Befehle

Die SavedModel-CLI unterstützt die folgenden zwei Befehle für ein SavedModel:

  • show , was zeigt die verfügbaren Berechnungen von einem SavedModel.
  • run , die eine Berechnung von einem SavedModel läuft.

show - Befehl

A SavedModel enthält eine oder mehr Modellvarianten (technisch, v1.MetaGraphDef s), ihre Tag-Sätze identifiziert. Um ein Modell zu dienen, könnte man sich fragen , welche Art von SignatureDef s in jeder Modellvariante ist, und was sind ihre Ein- und Ausgänge. Der show - Befehl können Sie den Inhalt des SavedModel in hierarchischer Reihenfolge untersuchen. Hier ist die Syntax:

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

Der folgende Befehl zeigt beispielsweise alle verfügbaren Tag-Sets im SavedModel:

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

Der folgende Befehl zeigt alle verfügbaren SignatureDef Schlüssel für einen Tag - Satz:

$ 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"

Wenn mehrere Tags im Tag-Set sind, müssen Sie alle Variablen angeben, getrennt jeder Tag durch ein Komma. Beispielsweise:

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

Um alle Eingaben zu zeigen und gibt TensorInfo für einen bestimmten SignatureDef , passieren in der SignatureDef Schlüssel zu signature_def Option. Dies ist sehr nützlich, wenn Sie den Tensorschlüsselwert, dtype und die Form der Eingabetensoren kennen möchten, um den Berechnungsgraphen später auszuführen. Beispielsweise:

$ 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

Um alle verfügbaren Informationen aus der SavedModel zu zeigen, verwenden Sie die --all Option. Beispielsweise:

$ 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 - Befehl

Rufen Sie das run eine Graphen Berechnung, vorbei Eingänge und dann die Anzeige (und optional zu speichern) die Ausgänge führen. Hier ist die Syntax:

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]

Der run verfügt über die folgenden drei Möglichkeiten , Eingaben in das Modell zu übergeben:

  • --inputs Option können Sie numpy ndarray in Dateien zu übergeben.
  • --input_exprs Option können Sie Python - Ausdrücke zu übergeben.
  • --input_examples Option ermöglicht es Ihnen passieren tf.train.Example .

--inputs

Zur Eingabe von Daten in Dateien übergeben, geben Sie die --inputs Option, die das folgende allgemeine Format verwendet :

--inputs <INPUTS>

wo INPUTS ist entweder der folgenden Formate:

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

Sie können mehrere Eingänge passieren. Wenn Sie mehrere Eingänge tun passieren, verwenden Sie ein Semikolon jedem der Eingänge zu trennen.

saved_model_cli Anwendungen numpy.load die Dateinamen zu laden. Der Dateiname kann in einem der folgenden Formate:

  • .npy
  • .npz
  • Gurkenformat

Eine .npy Datei enthält immer einen numpy ndarray. Daher beim Laden von einer .npy Datei, wird der Inhalt direkt an dem angegebenen Eingang Tensor zugeordnet werden. Wenn Sie eine variable_name mit dieser angeben .npy Datei, wird der variable_name ignoriert und eine Warnung ausgegeben.

Beim Laden von einer .npz (zip - Datei) können Sie optional einen variable_name geben Sie die Variable in der Zip - Datei zu identifizieren , für die Eingabe Tensor Schlüssel zu laden. Wenn Sie keinen variable_name angeben, wird die SavedModel CLI überprüfen , dass nur eine Datei in der ZIP - Datei enthalten ist und es für die angegebenen Eingang Tensor Schlüssel laden.

Beim Laden von einer Beize - Datei, wenn keine variable_name in den eckigen Klammern angegeben wird, was auch immer die in der Beize - Datei wird mit den angegebenen Eingang Tensor Schlüsseln übergeben werden. Andernfalls wird davon ausgehen , das SavedModel CLI ein Wörterbuch in der Beize - Datei gespeichert ist und der Wert auf den variable_name verwendet wird entspricht.

--input_exprs

Um Eingaben über Python - Ausdrücke übergeben, geben Sie die --input_exprs Option. Dies kann nützlich sein, wenn Sie keine Datendateien herumliegen haben, wollen aber trotzdem zur Vernunft das Modell überprüfen Sie mit einigen einfachen Eingaben, die die dtype und Form des Modells entsprechen SignatureDef s. Beispielsweise:

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

Zusätzlich zu Python-Ausdrücken können Sie auch numpy-Funktionen übergeben. Beispielsweise:

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

(Beachten Sie, dass das numpy Modul steht Ihnen als bereits vorhanden np .)

--input_examples

So übergeben tf.train.Example als Eingaben, die angeben --input_examples Option. Für jede Eingabetaste, dauert es eine Liste von Wörterbuch, wobei jedes Wörterbuch eine Instanz ist tf.train.Example . Die Wörterbuchschlüssel sind die Funktionen und die Werte sind die Wertelisten für jede Funktion. Beispielsweise:

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

Ausgabe speichern

Standardmäßig schreibt die SavedModel-CLI die Ausgabe in stdout. Wenn ein Verzeichnis zu übergeben wird --outdir Option, werden die Ausgänge gespeichert werden .npy Dateien nach der Ausgabe Tensor Tasten unter dem angegebenen Verzeichnis mit dem Namen.

Verwenden Sie --overwrite an vorhandene Ausgabedateien überschreiben.