דף זה תורגם על ידי Cloud Translation API.
Switch to English

שימוש בפורמט SavedModel

צפה ב TensorFlow.org הפעל ב- Google Colab צפה במקור ב- GitHub הורד מחברת

SavedModel מכיל תוכנית TensorFlow מלאה הכוללת משקולות וחישוב. הוא אינו דורש את הפעלת קוד בניית הדגם המקורי, מה שמקל על שיתוף או פריסה (עם TFLite , TensorFlow.js , TensorFlow Serving או TensorFlow Hub ).

מסמך זה מתעמק בחלק מהפרטים כיצד להשתמש ב- tf.saved_model api ברמה tf.saved_model :

יצירת מודל שמור מ- 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

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 Serving לחשוב על הרעננות היחסית.

אנו יכולים לטעון את ה- 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']

הפעלת מודל Saved ב- TensorFlow Serving

ניתן להשתמש ב- 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 ), אבל זה נדיר. ממשקי API היוצרים גרסאות מרובות של דגם כוללות 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, למשל קבצי טקסט המשמשים לאתחול טבלאות אוצר מילים. זה לא בשימוש בדוגמה זו.

ל- 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 פונקציה tf.function , לא נשמר שום קוד פייתון.

אם לא נשמר שום קוד פייתון, כיצד SavedModel יודע כיצד לשחזר את הפונקציה?

בקצרה, tf.function פועל על ידי התחקות אחר קוד הפיתון ליצירת ConcreteFunction (עטיפה tf.Graph סביב 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 מ- Keras מספק יותר פרטים מאשר __call__ רגיל כדי לטפל במקרים מתקדמים יותר של כוונון עדין. TensorFlow Hub ממליץ לספק את הדברים הבאים, אם ישים, ב- SavedModels המשותפים לצורך כוונון עדין:

  • אם הדגם משתמש בנשירה או בטכניקה אחרת בה המעבר קדימה שונה בין אימונים __call__ (כמו נורמליזציה של אצווה), שיטת __call__ נוקטת training= אופציונלי, מוערך בפייתון training= ארגומנט שברירת המחדל False אך ניתן להגדיר אותו כ- True .
  • לצד התכונה __call__ , ישנם .variable . .trainable_variable ו- .trainable_variable עם רשימות המשתנים המתאימות. משתנה שהיה ניתן להדרכה במקור אך מיועד .trainable_variables בזמן כוונון עדין מושמט מ- .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]])))
 
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 s מציין באופן אוטומטי חתימות הגשה, אך עלינו להכריז במפורש על חתימת הגשה עבור המודולים המותאמים אישית שלנו.

כברירת מחדל, אף חתימה לא מוכרזת על tf.Module מותאם אישית.

 assert len(imported.signatures) == 0
 

כדי להכריז על חתימת הגשה, ציין פונקציית בטון באמצעות signatures kwarg. בעת ציון חתימה יחידה, מפתח החתימה שלה יהיה 'serving_default' , שנשמר כ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY קבוע 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 שלך כדי להחזיר מילון שממפה שמות פלט ליציאות. שמות התשומות נגזרים משמות הארג של פונקצית פייתון.

 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 from 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 ולהפעיל אותו tf.saved_model.load .

 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.

טען מודל Saved ב- 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 מאפשר לך לאשר במהירות שהטיפוס והצורה של טנסור הקלט תואמים את הדגם. יתר על כן, אם ברצונך לבדוק את המודל שלך, אתה יכול להשתמש ב- CLI כדי לבצע בדיקת שפיות על ידי העברת תשומות לדוגמה בפורמטים שונים (למשל, ביטויים של פייתון) ואז להביא את הפלט.

התקן את ה- SavedModel CLI

באופן כללי, תוכלו להתקין את TensorFlow באחת משתי הדרכים הבאות:

  • על ידי התקנת בינארי TensorFlow שנבנה מראש.
  • על ידי בניית TensorFlow מקוד המקור.

אם התקנת את TensorFlow דרך בינארי TensorFlow שנבנה מראש, ה- SavedModel CLI כבר מותקן במערכת שלך bin/saved_model_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 הזמינים SignatureDef תג:

 $ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve
The given SavedModel `MetaGraphDef` contains `SignatureDefs` with the
following keys:
SignatureDef key: "classify_x2_to_y3"
SignatureDef key: "classify_x_to_y"
SignatureDef key: "regress_x2_to_y3"
SignatureDef key: "regress_x_to_y"
SignatureDef key: "regress_x_to_y2"
SignatureDef key: "serving_default"
 

אם ישנם תגיות מרובות בערכת התגים, עליך לציין את כל התגים, כאשר כל תג מופרד בפסיק. לדוגמה:

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

כדי להציג את כל תשומות ותפוקות TensorInfo עבור ספציפי SignatureDef , להעביר את SignatureDef מפתח signature_def האופציה. זה שימושי מאוד כאשר ברצונך לדעת את ערך מפתח הטנסור, dtype וצורתם של טנסי טווחי הקלט לצורך ביצוע גרף החישוב מאוחר יותר. לדוגמה:

 $ saved_model_cli show --dir \
/tmp/saved_model_dir --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):
  inputs['x'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: x:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['y'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: y:0
Method name is: tensorflow/serving/predict
 

כדי להציג את כל המידע זמין SavedModel, להשתמש --all האופציה. לדוגמה:

$ saved_model_cli show --dir /tmp/saved_model_dir --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['classify_x2_to_y3']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: x2:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['scores'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: y3:0
  Method name is: tensorflow/serving/classify

...

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['x'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: x:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['y'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: y:0
  Method name is: tensorflow/serving/predict

run פקודה

קרא לפקודת ההפעלה run חישוב גרף, העברת תשומות ואז הצגת (ושמירה אופציונלית) של היציאות. להלן התחביר:

 usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_def
                           SIGNATURE_DEF_KEY [--inputs INPUTS]
                           [--input_exprs INPUT_EXPRS]
                           [--input_examples INPUT_EXAMPLES] [--outdir OUTDIR]
                           [--overwrite] [--tf_debug]
 

פקודת run מספקת את שלוש הדרכים הבאות להעברת תשומות לדגם:

  • אפשרות --inputs מאפשרת לך להעביר ndarray numpy בקבצים.
  • --input_exprs אפשרות --input_exprs מאפשרת לך לעבור ביטויים של פייתון.
  • --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 מכיל תמיד ndarray מנוקב. לכן, בעת טעינה מקובץ .npy , התוכן יוקצה ישירות לטנזור הקלט שצוין. אם תציין VARIABLE_NAME עם זה .npy קובץ, VARIABLE_NAME יתעלם ואזהרה תונפק.

בעת טעינה מקובץ .npz (zip), באפשרותך לציין שם משתנה כדי לזהות את המשתנה בקובץ ה- zip לטעינה עבור מקש טנזור הקלט. אם לא תציין שם משתנה , ה- SavedModel CLI יבדוק שרק קובץ אחד נכלל בקובץ ה- zip ויטען אותו עבור מפתח טנזור הקלט שצוין.

בעת טעינה מקובץ חמוצים, אם לא צוין שם variable_name בסוגריים המרובעים, כל מה שנמצא בקובץ הכבישה יועבר למפתח טנזור הקלט שצוין. אחרת, SavedModel CLI תיטול מילון מאוחסן בקובץ החמוץ ואת הערך המתאים VARIABLE_NAME ישמש.

--input_exprs

כדי להעביר תשומות דרך ביטויי פייתון, ציין את האפשרות - --input_exprs . זה יכול להיות שימושי כאשר אין ברשותך קבצי נתונים, אך אתה עדיין מעוניין בשפיות לבדוק את המודל עם כמה כניסות פשוטות התואמות את dtype וצורה של SignatureDef s של הדגם. לדוגמה:

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

בנוסף לביטויי פייתון, ייתכן שתעבור גם פונקציות מטומטמות. לדוגמה:

 `<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 כדי להחליף קבצי פלט קיימים.