این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

با استفاده از قالب SavedModel

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub بارگیری نوت بوک

یک SavedModel حاوی یک برنامه کامل TensorFlow است ، از جمله وزن و محاسبه. این کار کد اصلی مدل سازی برای اجرا، که باعث می شود آن را برای به اشتراک گذاری و یا استقرار مفید (با نیاز ندارد TFLite ، TensorFlow.js ، TensorFlow خدمت یا TensorFlow توپی ).

این سند به برخی از جزئیات نحوه استفاده از API سطح پایین tf.saved_model :

ایجاد یک SavedModel از کراس

برای معرفی سریع ، این بخش یک مدل از قبل آموزش دیده کراس را صادر می کند و درخواست های طبقه بندی تصویر را با آن ارائه می دهد. بقیه راهنما جزئیات را پر می کند و در مورد راه های دیگر ایجاد 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

ما از تصویری از گریس هاپر به عنوان نمونه در حال استفاده و یک مدل طبقه بندی تصویر از قبل آموزش دیده کراس استفاده می کنیم زیرا استفاده از آن آسان است. مدل های سفارشی نیز کار می کنند ، و بعداً با جزئیات همراه می شوند.

 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 Servicing در مورد طراوت نسبی استدلال کنند.

ما می توانیم با استفاده از tf.saved_model.load ، 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)
 
Result after saving and loading:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

اجرای یک SavedModel در سرویس TensorFlow

SavedModels از پایتون قابل استفاده است (بیشتر در مورد آن در زیر) ، اما محیط های تولید به طور معمول بدون استفاده از کد پایتون از یک سرویس اختصاصی برای استنتاج استفاده می کنند. این کار با استفاده از TensorFlow Servicing از یک SavedModel آسان است.

برای اطلاعات بیشتر در مورد خدمت از جمله دستورالعمل نصب tensorflow_model_server در یک نوت بوک یا در دستگاه محلی خود ، به آموزش tensorflow_model_server Serving REST مراجعه کنید. به عنوان یک طرح سریع ، برای خدمت به مدل 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 )، اما این نادر است. 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 استفاده نمی شود ، یک فهرست دایرکتوری داشته باشد ، به عنوان مثال اطلاعاتی برای مصرف کنندگان در مورد آنچه باید با 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 ذخیره می شود ، هیچ کد پایتون ذخیره نمی شود.

اگر هیچ کد پایتون ذخیره نشده ، چگونه 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/tmpmjpd1j0o/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

تنظیم دقیق

یک SavedModel از کراس جزئیات بیشتری را نسبت به ساده __call__ برای ارائه موارد پیشرفته تر تنظیم دقیق ارائه می دهد. TensorFlow Hub توصیه می کند موارد زیر را در صورت لزوم در SavedModels به منظور تنظیم دقیق تنظیم کنید:

  • اگر این مدل از ترک تحصیل یا تکنیک دیگری استفاده کند که در آن گذرگاه بین تمرین و استنتاج تفاوت دارد (مانند عادی سازی دسته ای) ، روش __call__ یک training= اختیاری ، پایتون-ارزش گذاری شده training= آرگومان را می گیرد که به صورت پیش فرض به False می __call__ اما می تواند True باشد.
  • بعد به __call__ ویژگی، وجود دارد .variable و .trainable_variable ویژگی با لیست مربوطه متغیر. متغیری که در ابتدا قابل آموزش بود اما به معنای یخ .trainable_variables در تنظیم دقیق است از .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, ...

تعیین امضاها هنگام صادرات

ابزاری مانند saved_model_cli و saved_model_cli می توانند با SavedModels تعامل برقرار کنند. برای کمک به این ابزارها ، برای تعیین ویژگی های ConcreteFunctions ، باید امضای خدمت را مشخص کنیم. tf.keras.Model طور خودکار امضاهای سرویس را مشخص می کند ، اما ما باید صریحاً یک امضای سرویس را برای ماژول های سفارشی خود اعلام کنیم.

به طور پیش فرض ، هیچ امضایی در یک tf.Module سفارشی اعلام 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 خود را اصلاح کنید تا یک دیکشنری که نامهای خروجی را به خروجی ها نقشه می کند ، tf.function . نام ورودی ها از نام arg arg (تابع پایتون) گرفته شده است.

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

ذخیره شدهModels از Estimators

برآوردگرها SavedModels را از طریق tf.Estimator.export_saved_model . برای جزئیات بیشتر به راهنمای Estimator مراجعه کنید.

 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 s عملکردهای ورودی را tf.train.Example .

یک 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 می توانید از رابط خط فرمان (SavedModel) (CLI) استفاده کنید. به عنوان مثال ، می توانید از CLI برای بازرسی از SignatureDef مدل استفاده کنید. CLI شما را قادر می سازد تا به سرعت تأیید کنید که ورودی و شکل Tensor ورودی با مدل مطابقت دارد. علاوه بر این ، اگر می خواهید مدل خود را آزمایش کنید ، می توانید با وارد کردن ورودی های نمونه در قالب های مختلف (به عنوان مثال عبارات پایتون) و سپس واکشی خروجی ، از CLI برای انجام بررسی عقل استفاده کنید.

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 ) است که توسط مجموعه های برچسب آنها مشخص می شود. برای ارائه یک مدل ، ممکن است تعجب کنید که چه نوع 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 گزینه است. این بسیار مفید است وقتی می خواهید مقدار کلید tensor ، 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 گزینه --inputs شما را قادر می سازد ndarray numpy را در پرونده ها بگذرانید.
  • --input_exprs شما را قادر می سازد تا عبارات پایتون را منتقل کنید.
  • گزینه --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 ، محتوا مستقیماً به تانسور ورودی مشخص شده اختصاص داده می شود. اگر شما یک variable_name مشخص با .npy فایل، variable_name نادیده گرفته می شود و یک هشدار صادر خواهد شد.

هنگامی که بارگذاری از .npz فایل (فایل زیپ)، شما ممکن است به صورت اختیاری یک variable_name مشخص برای شناسایی متغیر در فایل زیپ برای کلید تانسور ورودی بارگذاری. اگر شما یک variable_name مشخص نیست، SavedModel CLI را بررسی خواهد کرد که تنها یک فایل در فایل زیپ گنجانده و بار آن را برای کلید تانسور ورودی مشخص شده است.

در هنگام بارگیری از یک پرونده ترشی ، اگر هیچ variable_name نامی در براکت های مربع مشخص نشده باشد ، هر آنچه که در پرونده ترشی وجود دارد به کلید ورودی تنسور ورودی منتقل می شود. غیر این صورت، SavedModel CLI فرض خواهد یک فرهنگ لغت در فایل ذخیره می شود و ترشی ارزش مربوط به variable_name استفاده خواهد شد.

--input_exprs

برای عبور ورودی از عبارات پایتون ، گزینه --input_exprs را مشخص کنید. این می تواند برای زمانی مفید باشد که فاقد پرونده های داده در اطراف باشید ، اما هنوز هم می خواهید عقل را مدل با چند ورودی ساده مطابقت با نوع و شکل SignatureDef s مدل بررسی کنید. مثلا:

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

علاوه بر عبارات پایتون ، شما همچنین می توانید عملکردهای 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 استفاده کنید.