Korzystanie z formatu SavedModel

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

SavedModel zawiera kompletny program TensorFlow, łącznie przeszkolonych parametrów (tj tf.Variable S) i obliczeń. To nie wymaga oryginalnego kodu modelu budynku do pracy, co czyni go użytecznym dla udostępniania i wdrażania z TFLite , TensorFlow.js , TensorFlow Serving lub TensorFlow Hub .

Możesz zapisać i wczytać model w formacie SavedModel, korzystając z następujących interfejsów API:

Tworzenie zapisanego modelu z Keras

Aby uzyskać krótkie wprowadzenie, ta sekcja eksportuje wstępnie przeszkolony model Keras i obsługuje z nim żądania klasyfikacji obrazów. Pozostała część przewodnika wypełni szczegóły i omówi inne sposoby tworzenia SavedModels.

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

Użyjesz obrazu Grace Hopper jako działającego przykładu i wstępnie wytrenowanego modelu klasyfikacji obrazów Keras, ponieważ jest łatwy w użyciu. Działają również modele niestandardowe, które zostaną szczegółowo omówione później.

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

Najważniejszą prognozą dla tego obrazu jest „mundur wojskowy”.

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

Zapisuj-path następująco konwencję używaną przez TensorFlow Serving którym ostatni komponent ścieżki ( 1/ tutaj) to numer wersji dla danego modelu - pozwala narzędzia jak Tensorflow Serving rozsądku o względnej świeżości.

Można załadować tył SavedModel w Pythonie z tf.saved_model.load i zobaczyć, jak obraz admirała Hoppera jest klasyfikowany.

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

Zaimportowane podpisy zawsze zwracają słowniki. Aby dostosować nazwy podpis i klucze słownika wyjście, patrz Określanie podpisów podczas eksportu .

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

Uruchamianie wnioskowania z SavedModel daje taki sam wynik jak oryginalny model.

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

Uruchamianie SavedModel w TensorFlow Serving

SavedModels można używać z Pythona (więcej na ten temat poniżej), ale środowiska produkcyjne zazwyczaj używają dedykowanej usługi do wnioskowania bez uruchamiania kodu Pythona. Jest to łatwe do skonfigurowania z SavedModel przy użyciu TensorFlow Serving.

Zobacz TensorFlow Serving samouczek REST dla przykładu tensorflow stażem end-to-end.

Format SavedModel na dysku

SavedModel to katalog zawierający zserializowane podpisy i stan potrzebny do ich uruchomienia, w tym wartości zmiennych i słowniki.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

W saved_model.pb przechowuje plików rzeczywista programu TensorFlow lub modelu, a zestaw wymienionych podpisów, każdy identyfikacji funkcji, która akceptuje i wytwarza wejść tensora tensora wyjść.

SavedModels może zawierać wiele odmian wzoru (wiele v1.MetaGraphDefs , zidentyfikowane z --tag_set flaga do saved_model_cli ), ale rzadko. API, które stwarzają wiele wariantów modelu obejmują tf.Estimator.experimental_export_all_saved_models oraz w 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"

variables katalog zawiera standardową kontrolny szkoleniowy (patrz przewodnik po przejściach szkoleniowych ).

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

assets katalog zawiera pliki używane przez wykres TensorFlow, na przykład pliki tekstowe używane do inicjalizacji tablic słownictwo. W tym przykładzie nie jest używany.

SavedModels może mieć assets.extra katalog dla wszystkich plików używanych przez nie na wykresie TensorFlow, na przykład informacji dla konsumentów o tym, co zrobić z SavedModel. Sam TensorFlow nie korzysta z tego katalogu.

Zapisywanie niestandardowego modelu

tf.saved_model.save podpory ratownicze tf.Module obiektów i jej podklas, takich jak tf.keras.Layer i tf.keras.Model .

Wygląd Chodźmy na przykład zapisywanie i przywracanie 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()

Po zapisaniu tf.Module wszelkie tf.Variable atrybuty, tf.function -decorated metod i tf.Module s znalezione przez rekurencyjnego przechodzenia są zapisywane. (Patrz poradnik Checkpoint się więcej o tym rekurencyjnego przechodzenia). Jednak każdy Python atrybuty, funkcje, a dane zostaną utracone. Oznacza to, że gdy tf.function jest zapisane, brak kodu Pythona zostanie zapisany.

Jeśli żaden kod Pythona nie zostanie zapisany, skąd SavedModel wie, jak przywrócić tę funkcję?

Pokrótce, tf.function działa poprzez śledzenie kodu Pythona generowania ConcreteFunction (wywoływalnym owinięcia tf.Graph ). Podczas zapisywania tf.function , jesteś naprawdę zapisywania tf.function dydaktycznego cache ConcreteFunctions.

Aby dowiedzieć się więcej na temat relacji między tf.function i ConcreteFunctions, zobacz przewodnik 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

Ładowanie i używanie niestandardowego modelu

Podczas ładowania SavedModel W Pythonie wszystkie tf.Variable atrybuty tf.function -decorated metod i tf.Module s przywracane są w tej samej strukturze obiektów jak oryginał zapisane 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

Ponieważ żaden kod Python jest zapisane, nazywając tf.function z nowym podpisem wejściowego zawiedzie:

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

Dostrajanie podstawowe

Dostępne są obiekty zmienne, a zaimportowane funkcje można cofnąć. To wystarczy do dostrojenia (tj. przekwalifikowania) SavedModel w prostych przypadkach.

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

Ogólne dostrajanie

SavedModel z Keras zapewnia więcej szczegółów niż zwykły __call__ zająć bardziej zaawansowanych przypadkach dostrajających. TensorFlow Hub zaleca udostępnienie następujących elementów, jeśli ma to zastosowanie, w SavedModels udostępnionych w celu dostrojenia:

  • Jeśli model zastosowania Odpad lub inną techniką, w której podaniu zależy od treningu i wnioskowania (np normalizacji wsadowym), The __call__ metoda pobiera opcjonalny, Python-wartościową training= argument, że domyślnie False , ale może być ustawiona na True .
  • Obok __call__ atrybutu, istnieje .variable i .trainable_variable atrybuty z odpowiednich list zmiennych. Zmienna, która była pierwotnie wyszkolić ale ma być zamrożona podczas dostrajania jest pominięty .trainable_variables .
  • Dla zachowania struktur, takich jak Keras reprezentujących regularizers masy atrybutami warstw lub pod-wzorów, nie może być również .regularization_losses atrybutów. Zawiera listę funkcji z zerowymi argumentami, których wartości mają na celu dodanie do całkowitej straty.

Wracając do pierwszego przykładu MobileNet, możesz zobaczyć niektóre z nich w akcji:

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

Określanie podpisów podczas eksportu

Narzędzia, takie jak TensorFlow Serving i saved_model_cli może wchodzić w interakcje z SavedModels. Aby pomóc tym narzędziom określić, których ConcreteFunctions użyć, musisz określić sygnatury obsługujące. tf.keras.Model s automatycznie określić obsługujących podpisy, ale musisz jawnie zadeklarować podpisu służący do naszych modułów niestandardowych.

Domyślnie żadne podpisy są zadeklarowane w niestandardowym tf.Module .

assert len(imported.signatures) == 0

Aby zadeklarować podpisu serwującą określ ConcreteFunction przy użyciu signatures kwarg. Podczas określania jednego podpisu, jego podpis będzie klucz 'serving_default' , który jest zapisany jako stałą 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']

Aby wyeksportować wiele podpisów, przekaż słownik kluczy podpisów do ConcreteFunctions. Każdy klucz podpisu odpowiada jednej konkretnej funkcji.

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

Domyślnie nazwy wyjście tensor są dość ogólne, jak output_0 . Aby kontrolować nazwy wyjścia, modyfikować swój tf.function wrócić słownika, który mapuje nazwy wyjściowych do wyjść. Nazwy wejść pochodzą od nazw argumentów funkcji Pythona.

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

Załaduj SavedModel w C++

C ++ wersja SavedModel ładowarka dostarcza API, aby załadować SavedModel ze ścieżki, pozwalając jednocześnie sessionoptions i RunOptions. Musisz określić tagi powiązane z wykresem, który ma zostać załadowany. Załadowana wersja SavedModel jest określana jako SavedModelBundle i zawiera MetaGraphDef oraz sesję, w której jest ładowana.

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

Szczegóły interfejsu wiersza poleceń SavedModel

Za pomocą interfejsu wiersza poleceń SavedModel (CLI) można sprawdzić i wykonać SavedModel. Na przykład, można użyć CLI do wglądu modelu SignatureDef s. CLI umożliwia szybkie potwierdzenie, że wejściowy typ i kształt Tensora pasują do modelu. Co więcej, jeśli chcesz przetestować swój model, możesz użyć interfejsu CLI do sprawdzenia poprawności, przekazując przykładowe dane wejściowe w różnych formatach (na przykład wyrażenia Pythona), a następnie pobierając dane wyjściowe.

Zainstaluj SavedModel CLI

Ogólnie rzecz biorąc, TensorFlow można zainstalować na jeden z dwóch poniższych sposobów:

  • Instalując gotowy plik binarny TensorFlow.
  • Budując TensorFlow z kodu źródłowego.

Jeśli zainstalowano TensorFlow poprzez gotowych TensorFlow binarnym, wówczas SavedModel CLI jest już zainstalowany w systemie na ścieżce, bin/saved_model_cli .

Jeśli zbudowany TensorFlow z kodu źródłowego, należy uruchomić następujące dodatkowe polecenia zbudować saved_model_cli :

$ bazel build tensorflow/python/tools:saved_model_cli

Przegląd poleceń

SavedModel CLI obsługuje następujące dwa polecenia na SavedModel:

  • show , co pokazuje obliczenia dostępne z SavedModel.
  • run , który prowadzi obliczenia z punktu A SavedModel.

show polecenie

SavedModel zawiera jeden lub więcej rodzajów wzorów (technicznie v1.MetaGraphDef y) określonych przez ich znaczników zestawów. Służyć model, można się zastanawiać, jaki rodzaj SignatureDef s są w każdej wersji modelu, i jakie są ich wejścia i wyjścia. show polecenia pozwalają zbadać zawartość SavedModel w porządku hierarchicznym. Oto składnia:

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

Na przykład poniższe polecenie pokazuje wszystkie dostępne zestawy tagów w SavedModel:

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

Poniższa komenda wszystkie dostępne SignatureDef klucze do zestawu tag:

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

Jeśli istnieje wiele tagów w tagu-zestawu, należy określić wszystkie znaczniki, każdy tag oddzielone przecinkiem. Na przykład:

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

Aby wyświetlić wszystkie wejścia i wyjścia TensorInfo zadaniu SignatureDef , przechodzą w SignatureDef klucz do signature_def opcji. Jest to bardzo przydatne, gdy chcesz poznać wartość klucza tensora, typ d i kształt tensorów wejściowych w celu późniejszego wykonania wykresu obliczeń. Na przykład:

$ 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

Aby wyświetlić wszystkie dostępne informacje w SavedModel użyj --all opcję. Na przykład:

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

Powoływania się na run programu do wykonania obliczeń, wykres, przechodząc wejść i wyświetlania (i opcjonalnie zapisywanie) wyjść. Oto składnia:

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]

run komenda zapewnia następujące trzy sposoby przekazać wejść do modelu:

  • --inputs opcja pozwala przejść numpy ndarray w plikach.
  • --input_exprs opcja pozwala przekazać wyrażeń Pythona.
  • --input_examples opcja pozwala przejść tf.train.Example .

--inputs

Do przekazywania danych wejściowych w plikach określ --inputs opcję, która przyjmuje następujący ogólny format:

--inputs <INPUTS>

WEJŚCIA gdzie jest jeden z następujących formatów:

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

Możesz przechodzić wieloma wejściami. Jeśli nie przechodzą wiele wejść, należy użyć średnika do oddzielenia każdego z wejść.

saved_model_cli zastosowania numpy.load załadowanie pliku. Nazwa pliku może być w dowolny z następujących formatów:

  • .npy
  • .npz
  • marynowany format

.npy plik zawsze zawiera numpy ndarray. Dlatego podczas załadunku z .npy pliku, zawartość będzie bezpośrednio przypisane do określonego wejścia tensora. Jeśli określisz nazwa_zmiennej z tym .npy pliku, variable_name będą ignorowane i ostrzeżenie zostanie wydana.

Podczas ładowania z .npz pliku (zip), można ewentualnie określić nazwa_zmiennej zidentyfikować zmienną w pliku zip, aby załadować klucza tensora wejściowego. Jeśli nie określisz nazwa_zmiennej The SavedModel CLI sprawdzi, że tylko jeden plik jest zawarty w pliku zip i załadować go do określonego klucza tensora wejściowego.

Podczas ładowania z pliku marynowane, jeśli nie variable_name podano w nawiasach kwadratowych, cokolwiek to jest wewnątrz pliku ogórka zostaną przekazane do określonego klucza tensora wejściowego. W przeciwnym razie, SavedModel CLI obejmie słownikiem jest przechowywany w pliku ogórka i wartość odpowiadająca Nazwa_zmiennej zostaną wykorzystane.

--input_exprs

Aby przejść wejść za pomocą wyrażeń Pythona określ --input_exprs opcję. Może to być przydatne, gdy nie masz plików danych leżące wokół, ale nadal chcą normalności sprawdzić model z kilku prostych wejść pasujących do dtype i kształt modelu SignatureDef s. Na przykład:

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

Oprócz wyrażeń Pythona możesz również przekazywać funkcje numpy. Na przykład:

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

(Należy pamiętać, że numpy moduł jest już dostępna jako np ).

--input_examples

Aby przejść tf.train.Example jako wejścia określ --input_examples opcję. Dla każdego klawisza wejściowego, trwa listę słownika, gdzie każdy słownika instancją tf.train.Example . Klucze słownika są funkcjami, a wartości są listami wartości dla każdej funkcji. Na przykład:

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

Zapisz dane wyjściowe

Domyślnie SavedModel CLI zapisuje dane wyjściowe na standardowe wyjście. Jeśli katalog jest przekazywana do --outdir opcji wyjścia zostanie zapisany jako .npy plików nazwanych kluczy wyjście tensorowych pod danym katalogu.

Użyj --overwrite nadpisać istniejące pliki wyjściowe.