
Как сохранить, загружать и развернуть модели с использованием TensorFlow SaveModel
30 июля 2025 г.Обзор контента
- Создание сохраненной модели из кераса
- Запуск сохраненной модели в Tensorflow Aerding
- Формат SaveedModel на диске
- Сохранение пользовательской модели
- Загрузка и использование пользовательской модели
- Основная точная настройка
- Общая точная настройка
- Указание подписей во время экспорта
- Прото-рассеивание
- Загрузите сохранение модели в C ++
- Детали интерфейса командной строки SavedModel
- Установите CLI SaveedModel
- Обзор команд
- Показать команду
- запустить команду
SaveedModel содержит полную программу тензора, включая обученные параметры (т.е.tf.Variable
S) и вычисления. Это не требует, чтобы исходный код создания моделей запускался, что делает его полезным для обмена или развертывания сTfliteВTensorflow.jsВTensorflow Aerding, илиTensorflow Hub.
Вы можете сохранить и загрузить модель в формате SaveedModel, используя следующие API:
- Низкий уровень
tf.saved_model
API. Этот документ описывает, как подробно использовать этот API.- Сохранять:
tf.saved_model.save(model, path_to_dir)
- Нагрузка:
model = tf.saved_model.load(path_to_dir)
- Сохранять:
- Высокий уровень
tf.keras.Model
API. Обратиться кКерас спасение и сериализуется руководствоПолем - Если вы просто хотите сэкономить/загружать веса во время тренировки, см.Руководство по контрольным точкамПолем
Осторожность:Модели TensorFlow - это код, и важно быть осторожным с ненадежным кодом. Узнайте больше в
Создание сохраненной модели из кераса
Deprecated: For Keras objects, it's recommended to use the new high-level .keras format and tf.keras.Model.export, as demonstrated in the guide here. The low-level SavedModel format continues to be supported for existing code.
Для быстрого введения в этом разделе экспортирует предварительно обученную модель керас и служит с ним запросами классификации изображений. Остальная часть руководства заполнит подробности и обсуждает другие способы создания SaveedModels.
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.list_physical_devices('GPU')
for device in physical_devices:
tf.config.experimental.set_memory_growth(device, 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.utils.load_img(file, target_size=[224, 224])
plt.imshow(img)
plt.axis('off')
x = tf.keras.utils.img_to_array(img)
x = tf.keras.applications.mobilenet.preprocess_input(
x[tf.newaxis,...])
Вы используете изображение Grace Hopper в качестве примера, и модель классификации изображений, предварительно обученной 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())
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)
Лучший прогноз для этого изображения - «военная форма».
mobilenet_save_path = os.path.join(tmpdir, "mobilenet/1/")
tf.saved_model.save(pretrained_model, mobilenet_save_path)
Переэскушечный путь следует соглашению, используемому Tensorflow Forming, где последний компонент Path (1/
Здесь) номер версии для вашей модели - он позволяет таким инструментам, как Tensorflow, служить рассуждением об относительной свежесть.
Вы можете загрузить сохраненную модель обратно в Python сtf.saved_model.load
И посмотрите, как классифицируется изображение адмирала Хоппера.
loaded = tf.saved_model.load(mobilenet_save_path)
print(list(loaded.signatures.keys())) # ["serving_default"]
Импортированные подписи всегда возвращают словаря. Для настройки имен подписей и ключей выходного слова, см.Указание подписей во время экспортаПолем
infer = loaded.signatures["serving_default"]
print(infer.structured_outputs)
Запуск вывода из SaveedModel дает тот же результат, что и исходная модель.
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)
Запуск сохраненной модели в Tensorflow Aerding
Сохраненные модели используются из Python (подробнее об этом ниже), но производственные среды обычно используют выделенную услугу для вывода без запуска кода Python. Это легко настроить из сохраненной модели, используя Tensorflow Aerd.
УвидетьTensorflow Учебник для отдыхадля примера сквозного проведения тензора.
Формат SaveedModel на диске
Сохраняющая модель - это каталог, содержащий сериализованные подписи, и состояние, необходимое для их запуска, включая переменные значения и словесные слова.
ls {mobilenet_save_path}
Аsaved_model.pb
Файл хранит фактическую программу TensorFlow или модель, а также набор именованных подписей, каждый из которых идентифицирует функцию, которая принимает тензоры и производит тензорные выходы.
Сохраненные модели могут содержать несколько вариантов модели (множественныеv1.MetaGraphDefs
, отождествляется с--tag_set
флагsaved_model_cli
), но это редко. API, которые создают несколько вариантов модели, включаютtf.Estimator.experimental_export_all_saved_models
и в TensorFlow 1.xtf.saved_model.Builder
Полем
saved_model_cli show --dir {mobilenet_save_path} --tag_set serve
Аvariables
каталог содержит стандартную тренировочную контрольную точку (см.Руководство по обучению контрольных точек)
ls {mobilenet_save_path}/variables
Аassets
Каталог содержит файлы, используемые на графике TensorFlow, например, текстовые файлы, используемые для инициализации словарных таблиц. Это не используется в этом примере.
Спасенные модели могут иметьassets.extra
Справочник для любых файлов, не используемых на графике TensorFlow, например, информация для потребителей о том, что делать со SavedModel. Сам TensorFlow не использует этот каталог.
Аfingerprint.pb
Файл содержитОтпечаток пальцаиз сохраненной модели, которая состоит из нескольких 64-битных хэшей, которые уникально идентифицируют содержимое сохраненной модели. API отпечатков пальцев в настоящее время экспериментально, ноtf.saved_model.experimental.read_fingerprint
можно использовать для чтения отпечатка пальца SaveedModel вtf.saved_model.experimental.Fingerprint
объект.
Сохранение пользовательской модели
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
-Корированные методы, иtf.Module
S, найденные через рекурсивное обход, сохраняются. (СмУчебное пособие по контрольно -пропускному пунктуДля получения дополнительной информации об этом рекурсивном обходе.) Однако любые атрибуты, функции и данные Python теряются. Это означает, что когдаtf.function
Сохраняется, код Python не сохранен.
Если код Python не сохранен, как SaveDmodel узнает, как восстановить функцию?
Вкратце,tf.function
Работает путем отслеживания кода Python, чтобы создать бетонную функцию (оболочка вокругtf.Graph
) При сохраненииtf.function
, вы действительно спасаетеtf.function
Кэш бетонных функций.
Чтобы узнать больше о отношениях междуtf.function
и конкретные функции, см.TF.Function GuideПолем
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)
Загрузка и использование пользовательской модели
Когда вы загружаете сохраненную модель в Python, всеtf.Variable
атрибуты,tf.function
-Корированные методы, и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'),), {})].
Основная точная настройка
Доступны переменные объекты, и вы можете отступить через импортированные функции. Этого достаточно для точной настройки (т.е. переподготовки) сохраненной модели в простых случаях.
optimizer = tf.keras.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()))
Общая точная настройка
SaveedModel из Keras предоставляетБолее подробная информациячем равнина__call__
Для рассмотрения более продвинутых случаев тонкой настройки. Tensorflow Hub рекомендует предоставить следующее, если применимо, в SavedModels, разделенных с целью точной настройки:
- Если модель использует отсевание или другой метод, при которой прямой проход отличается между обучением и выводом (например, нормализацией пакетов),
__call__
Метод принимает дополнительную, а также на питонеtraining=
аргумент, который по умолчаниюFalse
но может быть настроен наTrue
Полем - Рядом с
__call__
Атрибут, есть.variable
и.trainable_variable
Атрибуты с соответствующими списками переменных. Переменная, которая была первоначально обучена, но должна быть заморожена во время точной настройки, опущена из.trainable_variables
Полем - Ради карт, таких как кера, которые представляют собой регулялизации веса в качестве атрибутов слоев или подмоделей, также может быть
.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]])))
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]])))
Указание подписей во время экспорта
Инструменты, такие как Tensorflow Forming иsaved_model_cli
может взаимодействовать с SavedModels. Чтобы помочь этим инструментам определить, какие конкретные функции использовать, вам необходимо указать подписи обслуживания.tf.keras.Model
S автоматически указывает на обслуживающие подписи, но вам придется явно объявить подпись для наших пользовательских модулей.
Важный:Если вам не нужно экспортировать свою модель в среду, отличную от Tensorflow 2.x с Python, вам, вероятно, не нужно явно экспортировать подписи. Если вы ищете способ обеспечения входной подписи для определенной функции, см.input_signature
аргументtf.function
Полем
По умолчанию, в пользовательскомtf.Module
Полем
assert len(imported.signatures) == 0
Чтобы объявить подпись, укажите конкретную функцию, используяsignatures
Кварг. При указании одной подписи его подпись будет'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)
imported_with_signatures = tf.saved_model.load(module_with_signature_path)
list(imported_with_signatures.signatures.keys())
Чтобы экспортировать несколько подписей, передайте словарь фирменных клавиш в бетонные функции. Каждый ключ подписи соответствует одной конкретной функции.
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)
imported_with_multiple_signatures = tf.saved_model.load(module_multiple_signatures_path)
list(imported_with_multiple_signatures.signatures.keys())
По умолчанию имена выходных тензоров довольно общие, как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(None, 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})
imported_with_output_name = tf.saved_model.load(module_output_path)
imported_with_output_name.signatures['serving_default'].structured_outputs
Прото-рассеивание
Примечание:Эта функция будет частью релиза TensorFlow 2.15. В настоящее время доступно в ночной сборке, которую вы устанавливаете CQANpip install tf-nightly
Полем
Из -за пределов реализации Protobuf размеры прото не могут превышать 2 ГБ. Это может привести к следующим ошибкам при попытке сохранить очень большие модели:
ValueError: Message tensorflow.SavedModel exceeds maximum protobuf size of 2GB: ...
google.protobuf.message.DecodeError: Error parsing message as the message exceeded the protobuf limit with type 'tensorflow.GraphDef'
Если вы хотите сохранить модели, которые превышают предел 2 ГБ, вам нужно сохранить, используя новую опцию протокопта:
tf.saved_model.save(
...,
options=tf.saved_model.SaveOptions(experimental_image_format=True)
)
Больше информации можно найти вРуководство по библиотеке Proto Splitter /Полем
Загрузите сохранение модели в C ++
The C++ version of the SavedModel погрузчикПредоставляет API для загрузки сохраненной модели с пути, позволяя SessionOptions и Runoptions. Вы должны указать теги, связанные с загруженным графом. Загруженная версия SaveedModel называется SaveDmodelbundle и содержит метаграфдеф и сеанс, в который он загружается.
const string export_dir = ...
SavedModelBundle bundle;
...
LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain},
&bundle);
Детали интерфейса командной строки SavedModel
Вы можете использовать интерфейс командной строки SavedModel (CLI) для проверки и выполнения SaveedModel. Например, вы можете использовать CLI для проверки моделиSignatureDef
с CLI позволяет быстро подтвердить, что входной тензор dtype и форма соответствуют модели. Более того, если вы хотите проверить свою модель, вы можете использовать CLI для проверки здравомыслия, передавая входные входы в различных форматах (например, экспрессии Python), а затем получая выход.
Установите CLI SaveedModel
Вообще говоря, вы можете установить TensorFlow любым из следующих двух способов:
- Установив предварительно построенный бинар Tensorflow.
- Построив тензорфлоу из исходного кода.
Если вы установили TensorFlow через предварительно построенный двойной бинар TensorFlow, то CLI SaveedModel уже установлен на вашей системе в PathNamebin/saved_model_cli
Полем
Если вы построили TensorFlow из исходного кода, вы должны запустить следующую дополнительную команду, чтобы построитьsaved_model_cli
:
$ bazel build //tensorflow/python/tools:saved_model_cli
Обзор команд
CLI SaveedModel поддерживает следующие две команды на SaveedModel:
show
, который показывает вычисления, доступные из SaveedModel.run
, который запускает вычисление из SaveedModel.
show
командование
SaveedModel содержит один или несколько вариантов модели (технически,v1.MetaGraphDef
S), идентифицированные их метками. Чтобы обслуживать модель, вы можете задаться вопросом, что заSignatureDef
S находится в каждом варианте модели, и каковы их входы и выходы. Аshow
Команда позвольте вам исследовать содержимое сохраненной модели в иерархическом порядке. Вот синтаксис:
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
Чтобы показать всю доступную информацию в SaveedModel, используйте--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
Опция позволяет вам передавать Numpy Ndarray в файлах.--input_exprs
Опция позволяет вам передавать экспрессию Python.--input_examples
опция позволяет вам пройтиtf.train.Example
Полем
--inputs
Чтобы передавать входные данные в файлах, укажите--inputs
вариант, который принимает следующий общий формат:
--inputs <INPUTS>
гдеВходные данныеявляется одним из следующих форматов:
<input_key>=<filename>
<input_key>=<filename>[<variable_name>]
Вы можете пройти несколькоВходные данныеПолем Если вы передаете несколько входов, используйте полуколон, чтобы разделить каждый изВходные данныеПолем
saved_model_cli
Использованиеnumpy.load
Чтобы загрузитьимя файлаПолем Аимя файламожет быть в любом из следующих форматов:
.npy
.npz
- Формат рассола
А.npy
Файл всегда содержит Numpy Ndarray. Следовательно, при загрузке из.npy
Файл, содержимое будет напрямую назначено указанному тензору ввода. Если вы указалиvariable_nameс этим.npy
Файл,variable_nameбудет проигнорировано, и будет выпущено предупреждение.
При загрузке из.npz
(ZIP) файл, вы можете при желании указатьvariable_nameЧтобы идентифицировать переменную в файле ZIP для загрузки для клавиши входного тензора. Если вы не указалиvariable_name, CLI SaveedModel проверяет, что в файл ZIP включен только один файл и загружается его для указанного ключа ввода -тензора.
При загрузке из файла маринозов, если нетvariable_name
указывается в квадратных скобках, что бы ни находилось внутри файла рассола, будет передано в указанный ключ входного тензора. В противном случае, CLI SaveedModel предполагает, что в файле Pickle хранится словарь, а значение, соответствующееvariable_nameбудет использоваться.
--input_exprs
Чтобы пройти входы через экспрессии Python, укажите--input_exprs
вариант. Это может быть полезно, когда у вас нет файлов данных.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"]}]`
Сохранить вывод
По умолчанию CLI SaveedModel записывает вывод в Stdout. Если каталог передается--outdir
вариант, выходы будут сохранены как.npy
Файлы, названные в честь вывода тензорных клавиш в данном каталоге.
Использовать--overwrite
перезаписать существующие выходные файлы.
Первоначально опубликовано на
Оригинал