باستخدام تنسيق SavedModel

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

يحتوي A SavedModel برنامج TensorFlow كاملة، بما في ذلك معايير تدريب (أي tf.Variable ق) والحساب. والأمر لا يتطلب قانون البناء النموذج الأصلي للشوط، الأمر الذي يجعل من المفيد للمشاركة أو نشر مع TFLite ، TensorFlow.js ، TensorFlow خدمة ، أو TensorFlow المحور .

يمكنك حفظ وتحميل نموذج بتنسيق SavedModel باستخدام واجهات برمجة التطبيقات التالية:

إنشاء نموذج محفوظ من Keras

للحصول على مقدمة سريعة ، يقوم هذا القسم بتصدير نموذج Keras الذي تم تدريبه مسبقًا ويخدم طلبات تصنيف الصور معه. سيقوم باقي الدليل بملء التفاصيل ومناقشة طرق أخرى لإنشاء 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

بي إن جي

ستستخدم صورة 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())
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

أهم التنبؤات لهذه الصورة هو "الزي العسكري".

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

ومسار حفظ يتبع اتفاقية يستخدمها TensorFlow تخدم حيث المكون مسار الماضي ( 1/ هنا) هو رقم الإصدار للنموذج الخاص بك - أنها تتيح أدوات مثل Tensorflow خدمة إلى السبب حول نضارة النسبية.

يمكنك تحميل الجزء الخلفي SavedModel في بيثون مع 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)
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']

تشغيل SavedModel في عرض TensorFlow

يمكن استخدام SavedModels من Python (المزيد عن ذلك أدناه) ، لكن بيئات الإنتاج عادةً ما تستخدم خدمة مخصصة للاستدلال دون تشغيل كود Python. هذا سهل الإعداد من SavedModel باستخدام خدمة TensorFlow.

رؤية TensorFlow خدمة REST البرنامج التعليمي لنهاية إلى نهاية سبيل المثال التي تخدم tensorflow.

تنسيق SavedModel على القرص

SavedModel هو دليل يحتوي على التوقيعات المتسلسلة والحالة اللازمة لتشغيلها ، بما في ذلك القيم المتغيرة والمفردات.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

و saved_model.pb مخازن ملف البرنامج الفعلي TensorFlow، أو نموذج، ومجموعة من التوقيعات اسمه، كل التعرف على وظيفة أن يقبل مدخلات موتر وتنتج موتر النواتج.

قد تحتوي SavedModels المتغيرات المتعددة من طراز (متعددة v1.MetaGraphDefs ، حدد مع --tag_set العلم saved_model_cli )، ولكن هذا أمر نادر الحدوث. واجهات برمجة التطبيقات التي خلق بدائل متعددة من نموذج تشمل tf.Estimator.experimental_export_all_saved_models وفي 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 يحتوي الدليل نقطة تفتيش التدريب القياسية (انظر دليل لنقاط التفتيش التدريب ).

ls {mobilenet_save_path}/variables
variables.data-00000-of-00001  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 يتم حفظ الصورة وجدت عبر اجتياز العودية. (انظر البرنامج التعليمي نقطة تفتيش لمعرفة المزيد عن هذا اجتياز عودي). ومع ذلك، سمات أي بيثون، وظائف، وفقدان البيانات. وهذا يعني أنه عندما tf.function يتم حفظها، يتم حفظ أي رمز بيثون.

إذا لم يتم حفظ رمز Python ، فكيف يعرف SavedModel كيفية استعادة الوظيفة؟

لفترة وجيزة، tf.function يعمل عن طريق تتبع التعليمات البرمجية بايثون لتوليد ConcreteFunction (مجمع للاستدعاء حول tf.Graph ). عند حفظ 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/tmpoijnvh4d/module_no_signatures/assets

تحميل واستخدام نموذج مخصص

عند تحميل SavedModel في بيثون، كل tf.Variable الصفات، tf.function -decorated الأساليب، و tf.Module تتم استعادة الصورة في بنية الكائن بنفس حفظ الأصلي 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

لأنه يتم حفظ أي رمز بيثون، استدعاء 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

الضبط العام

A SavedModel من Keras توفر مزيد من التفاصيل من السهل __call__ لمعالجة الحالات الأكثر تقدما من صقل. يوصي TensorFlow Hub بتوفير ما يلي ، إن أمكن ، في SavedModels المشتركة لغرض الضبط الدقيق:

  • إذا الاستخدامات نموذج التسرب أو أسلوب آخر في الذي يختلف تمريرة إلى الأمام بين التدريب والاستدلال (مثل التطبيع دفعة)، و __call__ طريقة يأخذ اختياري بقيمة بيثون training= القول بأن التخلف إلى False ولكن يمكن وضعها ل True .
  • بجانب __call__ السمة، هناك .variable و .trainable_variable سمات مع قوائم المقابلة من المتغيرات. تم حذف متغير التي كانت قابلة للتدريب في الأصل ولكن من المفترض أن يتم تجميدها خلال صقل من .trainable_variables .
  • من أجل الأطر مثل Keras التي تمثل regularizers الوزن كما خصائص الطبقات أو النماذج الفرعية، ويمكن أيضا أن يكون هناك .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 خدمة و 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/tmpoijnvh4d/module_with_signature/assets
imported_with_signatures = tf.saved_model.load(module_with_signature_path)
list(imported_with_signatures.signatures.keys())
['serving_default']

لتصدير توقيعات متعددة ، قم بتمرير قاموس لمفاتيح التوقيع إلى ConcreteFunctions. يتوافق كل مفتاح توقيع مع وظيفة ملموسة واحدة.

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

افتراضيا، أسماء الناتج موتر هي عامة إلى حد ما، مثل output_0 . للسيطرة على أسماء المخرجات، عليك بتعديل tf.function لإرجاع القاموس تعين أسماء الإخراج إلى النواتج. يتم اشتقاق أسماء المدخلات من أسماء حجج دالة بايثون.

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

تحميل SavedModel في C ++

النسخة C ++ من SavedModel محمل يوفر 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 ثنائي، ثم يتم تثبيت SavedModel CLI بالفعل على النظام الخاص بك في مسار bin/saved_model_cli .

إذا كنت بنيت TensorFlow من شفرة المصدر، يجب تشغيل الأمر التالي إضافية لبناء saved_model_cli :

$ bazel build tensorflow/python/tools:saved_model_cli

نظرة عامة على الأوامر

يدعم SavedModel CLI الأمرين التاليين في SavedModel:

  • show ، مما يدل على الحسابات المتوفرة من SavedModel.
  • run ، الذي يدير حساب من SavedModel.

show القيادة

A 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 الخيار. يعد هذا مفيدًا جدًا عندما تريد معرفة قيمة مفتاح الموتر ونوع وشكل موتر الإدخال لتنفيذ الرسم البياني للحساب لاحقًا. فمثلا:

$ 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 خيار يتيح لك لتمرير ndarray نمباي في الملفات.
  • --input_exprs يمكنك خيار لتمرير عبارات بيثون.
  • --input_examples خيار يتيح لك لتمرير tf.train.Example .

--inputs

لتمرير إدخال البيانات في الملفات، حدد --inputs الخيار، والتي تأخذ الشكل العام ما يلي:

--inputs <INPUTS>

حيث المدخلات إما من الأشكال التالية:

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

تستطيع تمرير المدخلات المتعددة. إذا كنت لا تمر مدخلات متعددة، استخدم فاصلة منقوطة للفصل بين كل من المدخلات.

saved_model_cli الاستخدامات numpy.load لتحميل اسم الملف. قد يكون اسم الملف في أي من الأشكال التالية:

  • .npy
  • .npz
  • شكل مخلل

A .npy الملف يحتوي دائما ndarray نمباي. ولذلك، عند تحميل من .npy الملف، المحتوى سيتم تعيينها مباشرة إلى موتر الإدخال المحدد. إذا قمت بتحديد VARIABLE_NAME مع أن .npy الملف، سيتم تجاهل VARIABLE_NAME وسيصدر تحذيرا.

عند تحميل من .npz ملف (الرمز البريدي)، قد تحدد اختياريا VARIABLE_NAME لتحديد المتغير داخل ملف مضغوط لتحميل للحصول على مفتاح الإدخال الموترة. إذا لم تقم بتحديد VARIABLE_NAME، فإن SavedModel CLI تأكد من أن يتم تضمين ملف واحد فقط في ملف مضغوط وتحميله للحصول على مفتاح الإدخال موتر المحدد.

عند تحميل من ملف المخلل، إذا لم variable_name المحدد في الأقواس المربعة، أيا كان ذلك داخل ملف المخلل سيتم تمريرها إلى مفتاح الإدخال موتر المحدد. وإلا فإن SavedModel CLI تولي القاموس وتخزينها في ملف المخلل وسيتم استخدام القيمة المقابلة لVARIABLE_NAME.

--input_exprs

لتمرير المدخلات من خلال تعابير بيثون، حدد --input_exprs الخيار. هذا يمكن أن يكون مفيدا لأنه عندما لم يكن لديك ملفات البيانات الكذب حولها، ولكن لا تزال ترغب في التعقل والتحقق من نموذج مع بعض المدخلات البسيطة التي تتناسب مع dtype وشكل النموذج 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 CLI الإخراج إلى stdout. إذا تم تمرير دليل ل --outdir الخيار، سيتم حفظ المخرجات كما .npy ملفات سميت مفاتيح الناتج موتر تحت دليل معين.

استخدام --overwrite الكتابة الناتج الملفات الموجودة.