Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Menggunakan format SavedModel

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

A SavedModel berisi program TensorFlow lengkap, termasuk bobot dan perhitungan. Itu tidak memerlukan kode bangunan model asli untuk dijalankan, yang membuatnya berguna untuk berbagi atau menggunakan (dengan TFLite , TensorFlow.js , TensorFlow Serving , atau TensorFlow Hub ).

Dokumen ini menyelami beberapa detail tentang bagaimana menggunakan api tf.saved_model tingkat tf.saved_model :

Membuat Model Saved dari Keras

Untuk pengenalan singkat, bagian ini mengekspor model Keras yang telah dilatih sebelumnya dan melayani permintaan klasifikasi gambar. Sisa panduan ini akan mengisi detail dan membahas cara lain untuk membuat 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

Kami akan menggunakan gambar Grace Hopper sebagai contoh berjalan, dan model klasifikasi gambar pra-terlatih Keras karena mudah digunakan. Model khusus juga berfungsi, dan dibahas secara rinci nanti.

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

Prediksi teratas untuk gambar ini adalah "seragam militer".

 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

Save-path mengikuti konvensi yang digunakan oleh TensorFlow Serving di mana komponen path terakhir ( 1/ sini) adalah nomor versi untuk model Anda - ini memungkinkan alat seperti Tensorflow Serving untuk alasan tentang kesegaran relatif.

Kita dapat memuat SavedModel kembali ke Python dengan tf.saved_model.load dan melihat bagaimana gambar Admiral Hopper diklasifikasikan.

 loaded = tf.saved_model.load(mobilenet_save_path)
print(list(loaded.signatures.keys()))  # ["serving_default"]
 
['serving_default']

Tanda tangan yang diimpor selalu mengembalikan kamus. Untuk menyesuaikan nama tanda tangan dan kunci kamus keluaran, lihat Menentukan tanda tangan selama ekspor .

 infer = loaded.signatures["serving_default"]
print(infer.structured_outputs)
 
{'predictions': TensorSpec(shape=(None, 1000), dtype=tf.float32, name='predictions')}

Menjalankan inferensi dari SavedModel memberikan hasil yang sama dengan model aslinya.

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

Menjalankan Model Tersimpan di Penyajian TensorFlow

SavedModels dapat digunakan dari Python (lebih lanjut tentang itu di bawah), tetapi lingkungan produksi biasanya menggunakan layanan khusus untuk inferensi tanpa menjalankan kode Python. Ini mudah untuk diatur dari SavedModel menggunakan TensorFlow Serving.

Lihat tutorial TensorFlow Serving REST untuk detail lebih lanjut tentang penyajian, termasuk petunjuk untuk memasang tensorflow_model_server di buku catatan atau di mesin lokal Anda. Sebagai sketsa cepat, untuk melayani model mobilenet yang diekspor di atas, cukup arahkan server model di direktori SavedModel:

 nohup tensorflow_model_server \
  --rest_api_port=8501 \
  --model_name=mobilenet \
  --model_base_path="/tmp/mobilenet" >server.log 2>&1
 

Kemudian kirim permintaan.

 !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 dihasilkan identik dengan hasil dari Python.

Format SavedModel pada disk

A SavedModel adalah direktori yang berisi tandatangan berseri dan kondisi yang diperlukan untuk menjalankannya, termasuk nilai variabel dan kosa kata.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

File saved_model.pb menyimpan program TensorFlow yang sebenarnya, atau model, dan satu set tanda tangan bernama, masing-masing mengidentifikasi fungsi yang menerima input tensor dan menghasilkan output tensor.

SavedModels mungkin berisi beberapa varian dari model (multiple v1.MetaGraphDefs , diidentifikasi dengan --tag_set bendera untuk saved_model_cli ), tapi ini jarang terjadi. API yang membuat beberapa varian model termasuk tf.Estimator.experimental_export_all_saved_models dan di 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"

Direktori variables berisi pos pemeriksaan pelatihan standar (lihat panduan untuk pos pemeriksaan pelatihan ).

ls {mobilenet_save_path}/variables
variables.data-00000-of-00002  variables.data-00001-of-00002  variables.index

Direktori assets berisi file yang digunakan oleh grafik TensorFlow, misalnya file teks yang digunakan untuk menginisialisasi tabel kosakata. Itu tidak digunakan dalam contoh ini.

SavedModels dapat memiliki direktori assets.extra untuk file apa pun yang tidak digunakan oleh grafik TensorFlow, misalnya informasi untuk konsumen tentang apa yang harus dilakukan dengan SavedModel. TensorFlow sendiri tidak menggunakan direktori ini.

Menyimpan model khusus

tf.saved_model.save mendukung penyimpanan objek tf.Module dan subkelasnya, seperti tf.keras.Layer dan tf.keras.Model .

Mari kita lihat contoh menyimpan dan mengembalikan 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()
 

Bila Anda menyimpan sebuah tf.Module , setiap tf.Variable atribut, tf.function -decorated metode, dan tf.Module s ditemukan melalui traversal rekursif disimpan. (Lihat tutorial Checkpoint untuk informasi lebih lanjut tentang traversal rekursif ini.) Namun, semua atribut, fungsi, dan data Python hilang. Ini berarti bahwa ketika fungsi tf.function disimpan, tidak ada kode Python yang disimpan.

Jika tidak ada kode Python yang disimpan, bagaimana metode SavedModel tahu cara mengembalikan fungsi?

Secara singkat, tf.function dengan melacak kode Python untuk menghasilkan tf.Graph Beton (pembungkus yang dapat dipanggil di sekitar tf.Graph ). Saat menyimpan fungsi tf.function , Anda benar-benar menyimpan cache tf.function dari ConcreteFunctions.

Untuk mempelajari lebih lanjut tentang hubungan antara tf.function dan tf.function Beton, lihat panduan fungsi tf .

 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

Memuat dan menggunakan model khusus

Ketika Anda memuat SavedModel di Python, semua tf.Variable atribut, tf.function -decorated metode, dan tf.Module s dikembalikan dalam struktur objek yang sama seperti aslinya disimpan 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
 

Karena tidak ada kode Python yang disimpan, memanggil tf.function dengan tanda tangan input baru akan gagal:

 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'),), {})].

Penyetelan halus dasar

Objek variabel tersedia, dan kita dapat mundur melalui fungsi yang diimpor. Itu cukup untuk menyempurnakan (yaitu melatih kembali) sebuah SavedModel dalam kasus sederhana.

 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

General fine-tuning

A SavedModel dari Keras memberikan detail lebih dari sekadar __call__ untuk mengatasi kasus fine-tuning yang lebih canggih. TensorFlow Hub merekomendasikan untuk menyediakan yang berikut ini, jika ada, di SavedModels yang dibagikan untuk tujuan penyempurnaan:

  • Jika model menggunakan dropout atau teknik lain di mana umpan maju berbeda antara pelatihan dan inferensi (seperti normalisasi bets), metode __call__ mengambil argumen opsional, training= bernilai training= Python yang defaultnya menjadi False tetapi dapat disetel ke True .
  • Di sebelah atribut __call__ , ada atribut .variable dan .trainable_variable dengan daftar variabel yang sesuai. Variabel yang awalnya dapat dilatih tetapi dimaksudkan untuk dibekukan selama fine-tuning dihilangkan dari .trainable_variables .
  • Demi kerangka kerja seperti Keras yang mewakili pengatur berat sebagai atribut lapisan atau sub-model, bisa juga ada atribut .regularization_losses . Itu memegang daftar fungsi argumen-nol yang nilainya dimaksudkan untuk penambahan kerugian total.

Kembali ke contoh MobileNet awal, kita dapat melihat beberapa yang sedang beraksi:

 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, ...

Menentukan tanda tangan selama ekspor

Alat-alat seperti TensorFlow Serving dan saved_model_cli dapat berinteraksi dengan SavedModels. Untuk membantu alat ini menentukan Fungsi Beton mana yang akan digunakan, kita perlu menentukan tanda tangan penyajian. tf.keras.Model s secara otomatis menentukan tanda tangan penyajian, tetapi kami harus secara eksplisit mendeklarasikan tanda tangan penyajian untuk modul khusus kami.

Secara default, tidak ada tanda tangan yang dideklarasikan dalam custom tf.Module .

 assert len(imported.signatures) == 0
 

Untuk mendeklarasikan tanda tangan penyajian, tentukan Fungsi Beton menggunakan signatures kwarg. Saat menentukan satu tanda tangan, kunci tanda tangannya akan menjadi 'serving_default' , yang disimpan sebagai tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY konstan.EFAULT_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']

Untuk mengekspor beberapa tanda tangan, lewati kamus kunci tanda tangan ke Fungsi Beton. Setiap kunci tanda tangan sesuai dengan satu Fungsi Beton.

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

Secara default, nama tensor output cukup umum, seperti output_0 . Untuk mengontrol nama-nama keluaran, modifikasi tf.function Anda untuk mengembalikan kamus yang memetakan nama-nama keluaran ke keluaran. Nama input berasal dari nama fungsi Python 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')}

SavedModels dari Estimators

Estimator mengekspor SavedModels melalui tf.Estimator.export_saved_model . Lihat panduan untuk Pengukur untuk detail.

 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 ini menerima buffer protokol tf.Example , yang berguna untuk disajikan. Tapi kita juga bisa memuatnya dengan tf.saved_model.load dan jalankan dari 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 memungkinkan Anda membuat fungsi input yang mengambil tensor mentah daripada tf.train.Example . tf.train.Example s.

Load a SavedModel dalam C ++

Versi C ++ dari loader SavedModel menyediakan API untuk memuat SavedModel dari jalur, sambil memungkinkan SessionOptions dan RunOptions. Anda harus menentukan tag yang terkait dengan grafik yang akan dimuat. Versi dimuat dari SavedModel disebut sebagai SavedModelBundle dan berisi MetaGraphDef dan sesi di mana ia dimuat.

 const string export_dir = ...
SavedModelBundle bundle;
...
LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain},
               &bundle);
 

Detail antarmuka baris perintah SavedModel

Anda dapat menggunakan Antarmuka Baris Perintah CommandModel (CLI) SavedModel untuk memeriksa dan menjalankan SavedModel. Misalnya, Anda dapat menggunakan CLI untuk memeriksa SignatureDef s model. CLI memungkinkan Anda untuk dengan cepat mengonfirmasi bahwa tipe dan bentuk Tensor input cocok dengan model. Selain itu, jika Anda ingin menguji model Anda, Anda dapat menggunakan CLI untuk melakukan pemeriksaan kewarasan dengan mengirimkan input sampel dalam berbagai format (misalnya, ekspresi Python) dan kemudian mengambil output.

Instal CLM SavedModel

Secara umum, Anda dapat menginstal TensorFlow dengan salah satu dari dua cara berikut:

  • Dengan menginstal biner TensorFlow yang sudah dibangun sebelumnya.
  • Dengan membangun TensorFlow dari kode sumber.

Jika Anda menginstal TensorFlow melalui biner TensorFlow yang sudah dibangun sebelumnya, maka SavedModel CLI sudah diinstal pada sistem Anda di pathname bin/saved_model_cli .

Jika Anda membuat TensorFlow dari kode sumber, Anda harus menjalankan perintah tambahan berikut untuk membangun saved_model_cli :

 $ bazel build tensorflow/python/tools:saved_model_cli
 

Ikhtisar perintah

CLI SavedModel mendukung dua perintah berikut pada SavedModel:

  • show , yang menunjukkan perhitungan yang tersedia dari SavedModel.
  • run , yang menjalankan perhitungan dari SavedModel.

show perintah

Sebuah SavedModel berisi satu atau lebih varian model (secara teknis, v1.MetaGraphDef s), yang diidentifikasi oleh tag-set mereka. Untuk melayani model, Anda mungkin bertanya-tanya apa jenis SignatureDef di setiap varian model, dan apa input dan outputnya. Perintah show memungkinkan Anda memeriksa konten SavedModel dalam urutan hierarkis. Inilah sintaksinya:

 usage: saved_model_cli show [-h] --dir DIR [--all]
[--tag_set TAG_SET] [--signature_def SIGNATURE_DEF_KEY]
 

Misalnya, perintah berikut menunjukkan semua set tag yang tersedia di SavedModel:

 $ saved_model_cli show --dir /tmp/saved_model_dir
The given SavedModel contains the following tag-sets:
serve
serve, gpu
 

Perintah berikut menunjukkan semua kunci SignatureDef tersedia untuk satu set tag:

 $ 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"
 

Jika ada beberapa tag dalam set-tag, Anda harus menentukan semua tag, setiap tag dipisahkan oleh koma. Sebagai contoh:

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

Untuk menampilkan semua input dan output TensorInfo untuk SignatureDef tertentu, berikan kunci SignatureDef ke opsi signature_def . Ini sangat berguna ketika Anda ingin mengetahui nilai kunci tensor, tipe dan bentuk tensor input untuk mengeksekusi grafik perhitungan nanti. Sebagai contoh:

 $ 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
 

Untuk menampilkan semua informasi yang tersedia di SavedModel, gunakan opsi --all . Sebagai contoh:

$ 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 perintah

Aktifkan perintah run untuk menjalankan perhitungan grafik, meneruskan input dan kemudian menampilkan (dan secara opsional menyimpan) output. Inilah sintaksinya:

 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]
 

Perintah run menyediakan tiga cara berikut untuk meneruskan input ke model:

  • Opsi --inputs memungkinkan Anda untuk lulus ndarray numpy dalam file.
  • Opsi --input_exprs memungkinkan Anda untuk melewatkan ekspresi Python.
  • Opsi --input_examples memungkinkan Anda untuk mengirim tf.train.Example .

--inputs

Untuk meneruskan input data dalam file, tentukan opsi - --inputs , yang mengambil format umum berikut:

 --inputs <INPUTS>
 

di mana INPUT adalah salah satu dari format berikut:

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

Anda dapat melewati beberapa INPUT . Jika Anda memberikan beberapa input, gunakan tanda titik koma untuk memisahkan masing-masing INPUT .

saved_model_cli menggunakan numpy.load untuk memuat nama file . Nama file mungkin dalam salah satu format berikut:

  • .npy
  • .npz
  • format acar

File .npy selalu berisi ndarray numpy. Oleh karena itu, ketika memuat dari file .npy , konten akan langsung ditugaskan ke tensor input yang ditentukan. Jika Anda menentukan variabel_name dengan file .npy , variabel_name akan diabaikan dan peringatan akan dikeluarkan.

Saat memuat dari file .npz (zip), Anda dapat menentukan variabel_name untuk mengidentifikasi variabel dalam file zip yang akan dimuat untuk kunci tensor input. Jika Anda tidak menentukan nama variabel , CLI SavedModel akan memeriksa bahwa hanya satu file yang disertakan dalam file zip dan memuatnya untuk kunci tensor input yang ditentukan.

Saat memuat dari file acar, jika tidak ada variable_name yang ditentukan dalam tanda kurung, apa pun yang ada di dalam file acar akan diteruskan ke kunci tensor input yang ditentukan. Jika tidak, SavedModel CLI akan menganggap kamus disimpan dalam file acar dan nilai yang sesuai dengan variabel_name akan digunakan.

--input_exprs

Untuk meneruskan input melalui ekspresi Python, tentukan opsi --input_exprs . Ini bisa berguna ketika Anda tidak memiliki file data, tetapi tetap ingin memeriksa model dengan beberapa input sederhana yang cocok dengan dtype dan bentuk SignatureDef s model. Sebagai contoh:

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

Selain ekspresi Python, Anda juga dapat melewati fungsi numpy. Sebagai contoh:

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

(Perhatikan bahwa modul numpy sudah tersedia untuk Anda sebagai np .)

--input_examples

Untuk meneruskan tf.train.Example sebagai input, tentukan opsi --input_examples . Untuk setiap kunci input, dibutuhkan daftar kamus, di mana setiap kamus adalah turunan dari tf.train.Example . Kunci kamus adalah fitur dan nilainya adalah daftar nilai untuk setiap fitur. Sebagai contoh:

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

Simpan output

Secara default, SavedModel CLI menulis output ke stdout. Jika direktori dilewatkan ke opsi --outdir , output akan disimpan sebagai file .npy dinamai setelah kunci tensor keluaran di bawah direktori yang diberikan.

Gunakan --overwrite untuk menimpa file output yang ada.