ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

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

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

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

يتعمق هذا المستند في بعض التفاصيل حول كيفية استخدام tf.saved_model برمجة tf.saved_model ذات المستوى tf.saved_model :

إنشاء نموذج 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()
 
 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

بي إن جي

سنستخدم صورة 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)
 
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 ومعرفة كيفية تصنيف صورة Admiral Hopper.

 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 الناتجة مع نتائج بايثون.

تنسيق 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
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 ، على سبيل المثال الملفات النصية المستخدمة لتهيئة جداول المفردات. إنه غير مستخدم في هذا المثال.

قد يحتوي assets.extra دليل 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 يتم حفظ الصورة وجدت عبر اجتياز العودية. (راجع البرنامج التعليمي Checkpoint لمزيد من المعلومات حول هذا الاجتياح العودي.) ومع ذلك ، يتم فقد أي سمات ووظائف وبيانات Python. هذا يعني أنه عندما يتم حفظ وظيفة tf.function ، لا يتم حفظ كود Python.

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

باختصار ، تعمل tf.function خلال تتبع كود Python لإنشاء وظيفة الخرسانة (غلاف قابل للاستدعاء حول 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/tmpmjpd1j0o/module_no_signatures/assets

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

عند تحميل SavedModel في Python ، tf.Variable جميع السمات tf.Variable و tf.function الأساليب tf.Module و 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 استدعاء وظيفة 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'),), {})].

الضبط الدقيق الأساسي

تتوفر الكائنات المتغيرة ، ويمكننا تقديم الدعم من خلال الوظائف المستوردة. وهذا يكفي لضبط (SavrainModel) (أي إعادة تدريب) نموذج SavedMel في حالات بسيطة.

 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__ تأخذ __call__ اختياريًا بقيمة Python training= وسيطة تخلف افتراضيًا عن False ولكن يمكن تعيينها على True .
  • بجوار السمة __call__ ، هناك سمات .variable و .trainable_variable مع قوائم المتغيرات المقابلة. تم حذف .trainable_variables الأصل ولكن كان من المقرر تجميده أثناء الضبط .trainable_variables من .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 Serving و saved_model_cli التفاعل مع SavedModels. لمساعدة هذه الأدوات في تحديد وظائف الخرسانة التي نستخدمها ، نحتاج إلى تحديد توقيعات العرض. tf.keras.Model تلقائيًا ، ولكن سيتعين علينا الإعلان صراحةً عن توقيع العرض للوحدات المخصصة لدينا.

بشكل افتراضي ، لا يتم الإعلان عن التوقيعات في نموذج tf.Module مخصص.

 assert len(imported.signatures) == 0
 

لتعريف signatures العرض ، حدد وظيفة ConcreteFont باستخدام 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. كل مفتاح توقيع يتوافق مع وظيفة الخرسانة.

 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 عبر 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.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 الأولية بدلاً من tf.train.Example s.

قم بتحميل 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 s للنموذج. تتيح لك واجهة سطر الأوامر (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 الأمر

يحتوي SavedModel على واحد أو أكثر من متغيرات النماذج (من الناحية الفنية ، v1.MetaGraphDef s) ، المحددة بواسطة مجموعات العلامات الخاصة بها. لخدمة نموذج ، قد تتساءل عن نوع SignatureDef s الموجود في كل متغير نموذج ، وما هي المدخلات والمخرجات الخاصة بهم. يتيح لك الأمر 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 خيار --inputs من تمرير ndarray في الملفات.
  • --input_exprs الخيار --input_exprs من تمرير تعبيرات Python.
  • --input_examples الخيار --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 ملف .npy دائمًا على ndarray numpy. لذلك ، عند التحميل من ملف .npy ، سيتم تعيين المحتوى مباشرة إلى موتر الإدخال المحدد. إذا قمت بتحديد VARIABLE_NAME مع أن .npy الملف، سيتم تجاهل VARIABLE_NAME وسيصدر تحذيرا.

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

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

--input_exprs

لتمرير المدخلات عبر تعبيرات Python ، حدد الخيار --input_exprs . يمكن أن يكون هذا مفيدًا عندما لا يكون لديك ملفات بيانات موجودة ، ولكنك لا تزال ترغب في التحقق من النموذج باستخدام بعض المدخلات البسيطة التي تتطابق مع نوع وشكل SignatureDef المميز للنموذج. فمثلا:

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

بالإضافة إلى تعبيرات Python ، يمكنك أيضًا تمرير وظائف غير محدودة. فمثلا:

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

(لاحظ أن الوحدة النمطية numpy متاحة لك بالفعل على أنها np .)

--input_examples

لتمرير tf.train.Example كمدخلات ، حدد الخيار --input_examples . لكل مفتاح إدخال ، يأخذ قائمة من القاموس ، حيث يكون كل قاموس tf.train.Example من tf.train.Example . مفاتيح القاموس هي الميزات والقيم هي قوائم القيم لكل ميزة. فمثلا:

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

حفظ الناتج

بشكل افتراضي ، يكتب SavedModel CLI الإخراج إلى stdout. إذا تم تمرير دليل إلى خيار - --outdir ، فسيتم حفظ .npy كملفات .npy المسماة بعد مفاتيح موتر الإخراج تحت الدليل المحدد.

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