Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Использование формата SavedModel

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть источник на GitHub Скачать блокнот

SavedModel содержит полную программу TensorFlow, включая веса и вычисления. Он не требует наличия оригинальной модели здания код для запуска, что делает его полезным для совместного использования или развертывания (с TFLite , TensorFlow.js , TensorFlow сервировки или TensorFlow Hub ).

В этом документе рассматриваются некоторые детали использования низкоуровневого API- tf.saved_model :

Создание SavedModel из Кераса

Для быстрого ознакомления этот раздел экспортирует предварительно обученную модель Keras и предоставляет ей запросы на классификацию изображений. Остальная часть руководства заполнит детали и обсудит другие способы создания SavedModels.

 import os
import tempfile

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

tmpdir = tempfile.mkdtemp()
 
 physical_devices = tf.config.experimental.list_physical_devices('GPU')
if physical_devices:
  tf.config.experimental.set_memory_growth(physical_devices[0], True)
 
 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

Мы будем использовать изображение Грейс Хоппер в качестве рабочего примера и предварительно классифицированную модель классификации изображений Keras, поскольку она проста в использовании. Пользовательские модели тоже работают и подробно рассматриваются позже.

 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)
 
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/mobilenet/mobilenet_1_0_224_tf.h5
17227776/17225924 [==============================] - 1s 0us/step
Result before saving:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

Главный прогноз для этого изображения - «военная форма».

 mobilenet_save_path = os.path.join(tmpdir, "mobilenet/1/")
tf.saved_model.save(pretrained_model, mobilenet_save_path)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: /tmp/tmpmjpd1j0o/mobilenet/1/assets

Путь сохранения соответствует соглашению, используемому TensorFlow Serving, где последний компонент пути ( 1/ здесь) является номером версии для вашей модели - он позволяет таким инструментам, как Tensorflow Serving, рассуждать об относительной свежести.

Мы можем загрузить SavedModel обратно в Python с помощью tf.saved_model.load и посмотреть, как классифицируется изображение адмирала Хоппера.

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

Импортированные подписи всегда возвращают словари. Чтобы настроить имена подписей и выходные ключи словаря, см. Раздел «Указание подписей во время экспорта» .

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

Выполнение вывода из SavedModel дает тот же результат, что и исходная модель.

 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)
 
Result after saving and loading:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

Запуск SavedModel в обслуживании TensorFlow

SavedModels можно использовать из Python (подробнее об этом ниже), но производственные среды обычно используют выделенный сервис для вывода без выполнения кода Python. Это легко настроить из SavedModel с помощью TensorFlow Serving.

См. Учебное пособие TensorFlow Serving REST для получения более подробной информации об обслуживании, включая инструкции по установке tensorflow_model_server в ноутбуке или на вашем локальном компьютере. В качестве быстрого эскиза, для обслуживания модели mobilenet экспортируемой выше, просто укажите сервер модели в каталоге SavedModel:

 nohup tensorflow_model_server \
  --rest_api_port=8501 \
  --model_name=mobilenet \
  --model_base_path="/tmp/mobilenet" >server.log 2>&1
 

Тогда отправьте запрос.

 !pip install -q requests
import json
import numpy
import requests
data = json.dumps({"signature_name": "serving_default",
                   "instances": x.tolist()})
headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/mobilenet:predict',
                              data=data, headers=headers)
predictions = numpy.array(json.loads(json_response.text)["predictions"])
 

Полученные predictions идентичны результатам Python.

Формат SavedModel на диске

SavedModel - это каталог, содержащий сериализованные подписи и состояние, необходимое для их запуска, включая значения переменных и словари.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

В файле сохраненный_модель.pb хранится актуальная программа или модель saved_model.pb и набор именованных сигнатур, каждая из которых идентифицирует функцию, которая принимает тензорные входные данные и выдает тензорные выходные данные.

SavedModels может содержать несколько вариантов модели (несколько v1.MetaGraphDefs , идентифицируемых с --tag_set флага saved_model_cli для saved_model_cli ), но это редко. API, которые создают несколько вариантов модели, включают tf.Estimator.experimental_export_all_saved_models и в tf.saved_model.Builder 1.x tf.saved_model.Builder .

saved_model_cli show --dir {mobilenet_save_path} --tag_set serve
The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
SignatureDef key: "__saved_model_init_op"
SignatureDef key: "serving_default"

Каталог variables содержит стандартную контрольную точку обучения (см. Руководство по контрольным точкам обучения ).

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

Каталог assets содержит файлы, используемые графиком TensorFlow, например, текстовые файлы, используемые для инициализации словарных таблиц. Это не используется в этом примере.

SavedModels может иметь каталог assets.extra для любых файлов, не используемых графиком TensorFlow, например, информацию для потребителей о том, что делать с SavedModel. Сам TensorFlow не использует этот каталог.

Сохранение пользовательской модели

tf.saved_model.save поддерживает сохранение объектов tf.Module и его подклассов, таких как tf.keras.Layer и tf.keras.Model .

Давайте рассмотрим пример сохранения и восстановления 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()
 

При сохранении tf.Module любых tf.Variable атрибутов, tf.function -decorated методы и tf.Module s найдено с помощью рекурсивного обхода сохраняются. (Подробнее об этом рекурсивном обходе см. В руководстве по Checkpoint .) Однако все атрибуты, функции и данные Python теряются. Это означает, что при сохранении tf.function код Python не сохраняется.

Если код Python не сохранен, как SavedModel узнает, как восстановить функцию?

Вкратце, tf.function работает, отслеживая код Python для генерации ConcreteFunction (вызываемой оболочки вокруг tf.Graph ). tf.function функцию tf.function , вы действительно сохраняете кэш функции tf.function ConcreteFunctions.

Чтобы узнать больше об отношениях между tf.function и ConcreteFunctions, см. Руководство по 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/tmpmjpd1j0o/module_no_signatures/assets

Загрузка и использование пользовательской модели

При загрузке SavedModel в Python, все tf.Variable атрибутов, tf.function -decorated методы и tf.Module s восстанавливается в той же структуру объекта , как оригинал сохранен 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
 

Поскольку код Python не сохраняется, вызов функции tf.function с новой входной сигнатурой завершится неудачно:

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

Базовая подстройка

Переменные объекты доступны, и мы можем сделать бэкпроп через импортированные функции. Этого достаточно для точной настройки (т.е. переобучения) SavedModel в простых случаях.

 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

Генеральная подстройка

SavedModel от Keras предоставляет больше деталей, чем простой __call__ для решения более сложных случаев тонкой настройки. TensorFlow Hub рекомендует предоставить следующие из них, если это применимо, в общих ресурсах SavedModels для тонкой настройки:

  • Если в модели используется исключение или другой метод, в котором прямой проход отличается между обучением и выводом (например, нормализация пакета), метод __call__ принимает необязательный аргумент Python- __call__ training= который по умолчанию имеет значение False но может быть установлен в значение True .
  • Рядом с __call__ атрибутом, есть .variable и .trainable_variable атрибутов с соответствующими списками переменных. Переменная, которая была изначально обучаема, но должна быть заморожена во время тонкой настройки, исключена из .trainable_variables .
  • Ради каркасов, таких как Keras, которые представляют регуляризаторы веса в качестве атрибутов слоев или .regularization_losses , также может быть атрибут .regularization_losses . Он содержит список функций с нулевым аргументом, значения которых предназначены для добавления к полной потере.

Возвращаясь к первоначальному примеру MobileNet, мы можем увидеть некоторые из них в действии:

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

Указание подписей при экспорте

Такие инструменты, как TensorFlow Serving и saved_model_cli могут взаимодействовать с SavedModels. Чтобы помочь этим инструментам определить, какие конкретные функции использовать, нам нужно указать подписи для обслуживания. tf.keras.Model автоматически определяет обслуживающие подписи, но нам придется явно объявить обслуживающую подпись для наших пользовательских модулей.

По умолчанию никакие подписи не объявляются в пользовательском tf.Module .

 assert len(imported.signatures) == 0
 

Чтобы объявить обслуживающую подпись, укажите ConcreteFunction с помощью signatures kwarg. При указании одной подписи ее ключом подписи будет 'serving_default' , который сохраняется как константа 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/tmpmjpd1j0o/module_with_signature/assets

 imported_with_signatures = tf.saved_model.load(module_with_signature_path)
list(imported_with_signatures.signatures.keys())

 
['serving_default']

Чтобы экспортировать несколько подписей, передайте словарь ключей подписи в ConcreteFunctions. Каждый ключ подписи соответствует одной функции 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/tmpmjpd1j0o/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']

По умолчанию имена выходных тензоров являются довольно общими, как output_0 . Чтобы управлять именами выходов, измените вашу tf.function чтобы она возвращала словарь, который отображает имена выходов на выходы. Имена входных данных получены из имен аргументов функции 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/tmpmjpd1j0o/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')}

SavedModels от оценщиков

Оценщики экспортируют SavedModels через tf.Estimator.export_saved_model . См. Руководство к Оценщику для деталей.

 input_column = tf.feature_column.numeric_column("x")
estimator = tf.estimator.LinearClassifier(feature_columns=[input_column])

def input_fn():
  return tf.data.Dataset.from_tensor_slices(
    ({"x": [1., 2., 3., 4.]}, [1, 1, 0, 0])).repeat(200).shuffle(64).batch(16)
estimator.train(input_fn)

serving_input_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn(
  tf.feature_column.make_parse_example_spec([input_column]))
estimator_base_path = os.path.join(tmpdir, 'from_estimator')
estimator_path = estimator.export_saved_model(estimator_base_path, serving_input_fn)
 
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmp65c02lsq
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp65c02lsq', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/feature_column/feature_column_v2.py:540: Layer.add_variable (from tensorflow.python.keras.engine.base_layer_v1) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/ftrl.py:144: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp65c02lsq/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 0.6931472, step = 0
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 50...
INFO:tensorflow:Saving checkpoints for 50 into /tmp/tmp65c02lsq/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 50...
INFO:tensorflow:Loss for final step: 0.4131384.
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/saved_model/signature_def_utils_impl.py:145: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info.
INFO:tensorflow:Signatures INCLUDED in export for Classify: ['serving_default', 'classification']
INFO:tensorflow:Signatures INCLUDED in export for Regress: ['regression']
INFO:tensorflow:Signatures INCLUDED in export for Predict: ['predict']
INFO:tensorflow:Signatures INCLUDED in export for Train: None
INFO:tensorflow:Signatures INCLUDED in export for Eval: None
INFO:tensorflow:Restoring parameters from /tmp/tmp65c02lsq/model.ckpt-50
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: /tmp/tmpmjpd1j0o/from_estimator/temp-1594862628/saved_model.pb

Эта SavedModel принимает сериализованные tf.Example протокола tf.Example , которые полезны для обслуживания. Но мы также можем загрузить его с помощью tf.saved_model.load и запустить из Python.

 imported = tf.saved_model.load(estimator_path)

def predict(x):
  example = tf.train.Example()
  example.features.feature["x"].float_list.value.extend([x])
  return imported.signatures["predict"](
    examples=tf.constant([example.SerializeToString()]))
 
 print(predict(1.5))
print(predict(3.5))
 
{'all_classes': <tf.Tensor: shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.5451435]], dtype=float32)>, 'probabilities': <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.45485654, 0.5451435 ]], dtype=float32)>, 'logits': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.18106687]], dtype=float32)>, 'class_ids': <tf.Tensor: shape=(1, 1), dtype=int64, numpy=array([[1]])>, 'classes': <tf.Tensor: shape=(1, 1), dtype=string, numpy=array([[b'1']], dtype=object)>, 'all_class_ids': <tf.Tensor: shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>}
{'all_classes': <tf.Tensor: shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.21604054]], dtype=float32)>, 'probabilities': <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.7839595 , 0.21604055]], dtype=float32)>, 'logits': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[-1.2888912]], dtype=float32)>, 'class_ids': <tf.Tensor: shape=(1, 1), dtype=int64, numpy=array([[0]])>, 'classes': <tf.Tensor: shape=(1, 1), dtype=string, numpy=array([[b'0']], dtype=object)>, 'all_class_ids': <tf.Tensor: shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>}

tf.estimator.export.build_raw_serving_input_receiver_fn позволяет создавать функции ввода, которые принимают необработанные тензоры, а не tf.train.Example s.

Загрузите SavedModel в C ++

Версия загрузчика SavedModel для C ++ предоставляет API для загрузки SavedModel по пути, в то же время позволяя использовать SessionOptions и RunOptions. Вы должны указать теги, связанные с загружаемым графиком. Загруженная версия SavedModel называется SavedModelBundle и содержит MetaGraphDef и сеанс, в котором она загружается.

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

Подробная информация об интерфейсе командной строки SavedModel

Вы можете использовать интерфейс командной строки SavedModel (CLI) для проверки и выполнения SavedModel. Например, вы можете использовать CLI для проверки SignatureDef модели. CLI позволяет быстро подтвердить, что входной тип и форма Tensor соответствуют модели. Более того, если вы хотите протестировать свою модель, вы можете использовать CLI для проверки работоспособности, передавая вводные примеры в различных форматах (например, выражения Python), а затем выбирая выходные данные.

Установите SavedModel CLI

Вообще говоря, вы можете установить TensorFlow одним из следующих двух способов:

  • Устанавливая готовый бинарный файл TensorFlow.
  • Путем сборки TensorFlow из исходного кода.

Если вы установили TensorFlow через предварительно созданный двоичный файл TensorFlow, то CLI SavedModel уже установлен в вашей системе по пути bin/saved_model_cli .

Если вы saved_model_cli из исходного кода, вы должны выполнить следующую дополнительную команду для создания saved_model_cli :

 $ bazel build tensorflow/python/tools:saved_model_cli
 

Обзор команд

CLI SavedModel поддерживает следующие две команды в SavedModel:

  • show , который показывает вычисления, доступные из SavedModel.
  • run , который запускает вычисление из SavedModel.

команда show

SavedModel содержит один или несколько вариантов модели (технически, v1.MetaGraphDef ), идентифицируемых по их наборам тегов. Чтобы обслуживать модель, вы можете задаться вопросом, что это за SignatureDef в каждом варианте модели и каковы их входы и выходы. Команда show позволяет вам просматривать содержимое SavedModel в иерархическом порядке. Вот синтаксис:

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

Например, следующая команда показывает все доступные наборы тегов в SavedModel:

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

Следующая команда показывает все доступные ключи SignatureDef для набора тегов:

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

Если в наборе тегов есть несколько тегов, вы должны указать все теги, каждый тег должен быть разделен запятой. Например:

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

Чтобы показать все входные и выходные данные TensorInfo для определенного SignatureDef , передайте ключ SignatureDef в параметр signature_def . Это очень полезно, когда вы хотите узнать значение ключа тензора, dtype и форму входных тензоров для последующего выполнения графика вычислений. Например:

 $ 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
 

Чтобы показать всю доступную информацию в SavedModel, используйте параметр --all . Например:

$ 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 команду

Вызовите команду run для запуска вычисления графа, передачи входных данных, а затем отображения (и, при необходимости, сохранения) выходных данных. Вот синтаксис:

 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 предоставляет следующие три способа передачи входных данных в модель:

  • --inputs позволяет вам передавать numy ndarray в файлах.
  • --input_exprs позволяет передавать выражения Python.
  • --input_examples позволяет вам передать tf.train.Example .

--inputs

Чтобы передать входные данные в файлы, укажите параметр --inputs , который имеет следующий общий формат:

 --inputs <INPUTS>
 

где INPUTS имеет один из следующих форматов:

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

Вы можете передать несколько ВХОДОВ . Если вы передаете несколько входов, используйте точку с запятой для разделения каждого из ВХОДОВ .

saved_model_cli использует numpy.load для загрузки имени файла . Имя файла может быть в любом из следующих форматов:

  • .npy
  • .npz
  • формат рассола

Файл .npy всегда содержит Nundy ndarray. Поэтому при загрузке из файла .npy содержимое будет напрямую назначено указанному входному тензору. Если вы укажете имя_переменной в этом файле .npy , имя_переменной будет проигнорировано и будет выдано предупреждение.

При загрузке из .npz (zip) вы можете при желании указать переменную_имя, чтобы идентифицировать переменную в файле zip для загрузки для входного тензорного ключа. Если вы не укажете имя_ переменной , CLI SavedModel проверит, что в zip-файл включен только один файл, и загрузит его для указанного ключа входного тензора.

При загрузке из файла консервирования, если в квадратных скобках не указано variable_name , все, что находится внутри файла консервирования, будет передано указанному входному тензорному ключу. В противном случае интерфейс командной строки SavedModel будет предполагать, что в файле pickle хранится словарь, и будет использоваться значение, соответствующее variable_name .

--input_exprs

Чтобы передать входные данные через выражения Python, укажите параметр --input_exprs . Это может быть полезно, когда у вас нет лежащих файлов данных, но вы все еще хотите проверить работоспособность модели с помощью простых входных данных, которые соответствуют типу d и форме SignatureDef модели. Например:

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

В дополнение к выражениям Python вы также можете передавать numpy функции. Например:

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

(Обратите внимание, что модуль numpy уже доступен для вас как np .)

--input_examples

Чтобы передать tf.train.Example качестве входных данных, укажите параметр --input_examples . Для каждого ключа ввода требуется список словаря, где каждый словарь является экземпляром tf.train.Example . Ключи словаря - это функции, а значения - списки значений для каждой функции. Например:

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

Сохранить вывод

По умолчанию интерфейс командной строки SavedModel записывает выходные данные в стандартный вывод. Если каталог передан параметру --outdir , выходные данные будут сохранены в .npy файлов .npy названных в соответствии с тензорными ключами вывода в данном каталоге.

Используйте --overwrite чтобы перезаписать существующие выходные файлы.