Trang này được dịch bởi Cloud Translation API.
Switch to English

Sử dụng định dạng SavingModel

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải vở

Một SavingModel chứa một chương trình TensorFlow hoàn chỉnh, bao gồm trọng lượng và tính toán. Nó không yêu cầu mã xây dựng mô hình ban đầu để chạy, điều này giúp ích cho việc chia sẻ hoặc triển khai (với TFLite , TensorFlow.js , TensorFlow Serving hoặc TensorFlow Hub ).

Tài liệu này đi sâu vào một số chi tiết về cách sử dụng api tf.saved_model cấp thấp:

Tạo một SavingModel từ Keras

Để giới thiệu nhanh, phần này xuất một mô hình Keras được đào tạo trước và phục vụ các yêu cầu phân loại hình ảnh với nó. Phần còn lại của hướng dẫn sẽ điền chi tiết và thảo luận về các cách khác để tạo SavingModels.

 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

Chúng tôi sẽ sử dụng hình ảnh của Grace Hopper làm ví dụ đang chạy và mô hình phân loại hình ảnh được đào tạo trước của Keras vì nó dễ sử dụng. Các mô hình tùy chỉnh cũng hoạt động và được đề cập chi tiết sau.

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

Dự đoán hàng đầu cho hình ảnh này là "quân phục".

 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

Đường dẫn lưu theo quy ước được sử dụng bởi TensorFlow Phục vụ trong đó thành phần đường dẫn cuối cùng ( 1/ ở đây) là số phiên bản cho mô hình của bạn - nó cho phép các công cụ như Tensorflow Phục vụ lý do về độ mới tương đối.

Chúng ta có thể tải SavingModel trở lại vào Python bằng tf.saved_model.load và xem hình ảnh của Đô đốc Hopper được phân loại như thế nào.

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

Chữ ký nhập khẩu luôn trả lại từ điển. Để tùy chỉnh tên chữ ký và khóa từ điển đầu ra, hãy xem Xác định chữ ký trong khi xuất .

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

Chạy suy luận từ SavingModel cho kết quả giống như mô hình ban đầu.

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

Chạy một SavingModel trong Dịch vụ TensorFlow

SavingModels có thể sử dụng được từ Python (nhiều hơn ở bên dưới), nhưng môi trường sản xuất thường sử dụng một dịch vụ chuyên dụng để suy luận mà không chạy mã Python. Điều này rất dễ dàng để thiết lập từ SavingModel bằng cách sử dụng Dịch vụ TensorFlow.

Xem hướng dẫn REST phục vụ TensorFlow để biết thêm chi tiết về việc phục vụ, bao gồm các hướng dẫn để cài đặt tensorflow_model_server trong sổ ghi chép hoặc trên máy cục bộ của bạn. Như một bản phác thảo nhanh, để phục vụ mô hình mobilenet xuất ở trên, chỉ cần trỏ máy chủ mô hình vào thư mục SavingModel:

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

Sau đó gửi yêu cầu.

 !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"])
 

Các predictions kết quả giống hệt với kết quả từ Python.

Định dạng SavingModel trên đĩa

Một SavingModel là một thư mục chứa chữ ký được tuần tự hóa và trạng thái cần thiết để chạy chúng, bao gồm các giá trị biến và từ vựng.

ls {mobilenet_save_path}
assets  saved_model.pb  variables

Tệp saved_model.pb lưu trữ chương trình hoặc mô hình TensorFlow thực tế và một bộ chữ ký được đặt tên, mỗi xác định một chức năng chấp nhận đầu vào tenxơ và tạo đầu ra tenxơ.

SavedModels có thể chứa nhiều biến thể của mô hình (nhiều v1.MetaGraphDefs , xác định với --tag_set cờ để saved_model_cli ), nhưng điều này là hiếm. Các API tạo ra nhiều biến thể của một mô hình bao gồm tf.Estimator.experimental_export_all_saved_models và trong 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"

Thư mục variables chứa một điểm kiểm tra đào tạo tiêu chuẩn (xem hướng dẫn về điểm kiểm tra đào tạo ).

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

Thư mục assets chứa các tệp được sử dụng bởi biểu đồ TensorFlow, ví dụ các tệp văn bản được sử dụng để khởi tạo các bảng từ vựng. Nó không được sử dụng trong ví dụ này.

SavingModels có thể có một thư mục assets.extra cho bất kỳ tệp nào không được sử dụng bởi biểu đồ TensorFlow, ví dụ thông tin cho người tiêu dùng về những việc cần làm với SavingModel. Bản thân TensorFlow không sử dụng thư mục này.

Lưu một mô hình tùy chỉnh

tf.saved_model.save hỗ trợ lưu các đối tượng tf.Module và các lớp con của nó, như tf.keras.Layertf.keras.Model .

Hãy xem xét một ví dụ về lưu và khôi phục một 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()
 

Khi bạn tiết kiệm một tf.Module , bất kỳ tf.Variable thuộc tính, tf.function -decorated phương pháp, và tf.Module s tìm thấy qua traversal đệ quy được lưu. (Xem hướng dẫn về Điểm kiểm tra để biết thêm về giao dịch đệ quy này.) Tuy nhiên, mọi thuộc tính, hàm và dữ liệu của Python đều bị mất. Điều này có nghĩa là khi một tf.function được lưu, không có mã Python nào được lưu.

Nếu không có mã Python nào được lưu, thì SavingModel biết cách khôi phục chức năng như thế nào?

Tóm lại, tf.function hoạt động bằng cách truy tìm mã Python để tạo ConcreteFunction (trình bao bọc có thể gọi được xung quanh tf.Graph ). Khi lưu một tf.function , bạn thực sự đang lưu bộ nhớ cache của ConcreteFifts của tf.function .

Để tìm hiểu thêm về mối quan hệ giữa tf.function và ConcreteFifts, hãy xem hướng dẫn tf.feft .

 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

Đang tải và sử dụng mô hình tùy chỉnh

Khi bạn tải một SavingModel trong Python, tất cả các thuộc tính tf.Variable , tf.function -decorated và tf.Module s được khôi phục trong cùng cấu trúc đối tượng như tf.Module đã lưu ban đầu.

 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
 

Vì không có mã Python nào được lưu, việc gọi một tf.function bằng chữ ký đầu vào mới sẽ thất bại:

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

Tinh chỉnh cơ bản

Các đối tượng biến có sẵn và chúng ta có thể sao lưu thông qua các hàm được nhập. Điều đó là đủ để tinh chỉnh (tức là đào tạo lại) một SavingModel trong các trường hợp đơn giản.

 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

Tinh chỉnh chung

Một SavingModel từ Keras cung cấp nhiều chi tiết hơn một __call__ đơn giản để giải quyết các trường hợp tinh chỉnh nâng cao hơn. TensorFlow Hub khuyên bạn nên cung cấp những thứ sau đây, nếu có thể, trong SavingModels được chia sẻ cho mục đích tinh chỉnh:

  • Nếu mô hình sử dụng bỏ học hoặc một kỹ thuật khác trong đó chuyển tiếp chuyển tiếp khác nhau giữa đào tạo và suy luận (như chuẩn hóa hàng loạt), phương thức __call__ lấy một đối số tùy chọn, training= có giá trị Python training= mặc định thành False nhưng có thể được đặt thành True .
  • Bên cạnh thuộc tính __call__ , có các thuộc tính .variable.trainable_variable với danh sách các biến tương ứng. Một biến ban đầu có thể huấn luyện được nhưng có nghĩa là bị đóng băng trong quá trình tinh chỉnh được bỏ qua từ .trainable_variables .
  • Vì lợi ích của các khung như Kera đại diện cho các bộ chỉnh tần số như các thuộc tính của các lớp hoặc các mô hình con, cũng có thể có một thuộc tính .regularization_losses . Nó chứa một danh sách các hàm đối số bằng không có giá trị được dùng để cộng vào tổng tổn thất.

Quay trở lại ví dụ MobileNet ban đầu, chúng ta có thể thấy một số trong số đó đang hoạt động:

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

Xác định chữ ký trong quá trình xuất

Các công cụ như TensorFlow Serving và saved_model_cli có thể tương tác với SavingModels. Để giúp các công cụ này xác định nên sử dụng ConcreteFifts nào, chúng tôi cần chỉ định chữ ký phục vụ. tf.keras.Model s tự động chỉ định chữ ký phục vụ, nhưng chúng tôi sẽ phải khai báo rõ ràng chữ ký phục vụ cho các mô-đun tùy chỉnh của chúng tôi.

Theo mặc định, không có chữ ký nào được khai báo trong một tf.Module tùy chỉnh.

 assert len(imported.signatures) == 0
 

Để khai báo chữ ký phục vụ, chỉ định Hàm cụ thể bằng cách sử dụng signatures kwarg. Khi chỉ định một chữ ký, khóa chữ ký của nó sẽ là 'serving_default' , được lưu dưới dạng hằng số 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']

Để xuất nhiều chữ ký, chuyển một từ điển các khóa chữ ký cho ConcreteFifts. Mỗi khóa chữ ký tương ứng với một 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']

Theo mặc định, tên output_0 đầu ra khá chung chung, như output_0 . Để kiểm soát tên của đầu ra, hãy sửa đổi tf.function của bạn để trả về một từ điển ánh xạ tên đầu ra thành đầu ra. Tên của các yếu tố đầu vào được lấy từ tên arg của hàm 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')}

SavingModels từ Công cụ ước tính

Công cụ ước tính xuất SavingModels thông qua tf.Estimator.export_saved_model . Xem hướng dẫn để ước tính để biết chi tiết.

 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

SavingModel này chấp nhận bộ đệm giao thức tf.Example được tuần tự hóa, rất hữu ích cho việc phục vụ. Nhưng chúng ta cũng có thể tải nó bằng tf.saved_model.load và chạy nó từ 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 cho phép bạn tạo các hàm đầu vào có các tenxơ thô thay vì tf.train.Example s.

Tải một SavingModel trong C ++

Phiên bản C ++ của trình tải SavingModel cung cấp API để tải SavingModel từ một đường dẫn, đồng thời cho phép SessionOptions và RunOptions. Bạn phải chỉ định các thẻ liên quan đến biểu đồ sẽ được tải. Phiên bản đã tải của SavingModel được gọi là SavingModelBundle và chứa MetaGraphDef và phiên mà nó được tải.

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

Chi tiết về giao diện dòng lệnh SavingModel

Bạn có thể sử dụng Giao diện dòng lệnh SavingModel (CLI) để kiểm tra và thực thi một SavingModel. Ví dụ: bạn có thể sử dụng CLI để kiểm tra các SignatureDef của mô hình. CLI cho phép bạn nhanh chóng xác nhận rằng kiểu dtype đầu vào và hình dạng phù hợp với mô hình. Hơn nữa, nếu bạn muốn kiểm tra mô hình của mình, bạn có thể sử dụng CLI để kiểm tra độ chính xác bằng cách chuyển các đầu vào mẫu theo các định dạng khác nhau (ví dụ: biểu thức Python) và sau đó tìm nạp đầu ra.

Cài đặt SavingModel CLI

Nói rộng hơn, bạn có thể cài đặt TensorFlow theo một trong hai cách sau:

  • Bằng cách cài đặt một nhị phân TensorFlow dựng sẵn.
  • Bằng cách xây dựng TensorFlow từ mã nguồn.

Nếu bạn đã cài đặt TensorFlow thông qua tệp nhị phân TensorFlow dựng sẵn, thì CLM đã lưu đã được cài đặt trên hệ thống của bạn tại tên đường dẫn bin/saved_model_cli .

Nếu bạn đã xây dựng TensorFlow từ mã nguồn, bạn phải chạy lệnh bổ sung sau để xây dựng saved_model_cli :

 $ bazel build tensorflow/python/tools:saved_model_cli
 

Tổng quan về các lệnh

SavingModel CLI hỗ trợ hai lệnh sau trên SavingModel:

  • show , hiển thị các tính toán có sẵn từ SavingModel.
  • run , chạy một tính toán từ SavingModel.

show lệnh

Một SavingModel chứa một hoặc nhiều biến thể mô hình (về mặt kỹ thuật, v1.MetaGraphDef s), được xác định bởi các bộ thẻ của chúng. Để phục vụ một mô hình, bạn có thể tự hỏi loại SignatureDef nào trong mỗi biến thể của mô hình và đầu vào và đầu ra của chúng là gì. Lệnh show cho phép bạn kiểm tra nội dung của SavingModel theo thứ tự phân cấp. Đây là cú pháp:

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

Ví dụ: lệnh sau hiển thị tất cả các bộ thẻ có sẵn trong SavingModel:

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

Lệnh sau đây hiển thị tất cả các khóa SignatureDef có sẵn cho một bộ thẻ:

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

Nếu có nhiều thẻ trong bộ thẻ, bạn phải chỉ định tất cả các thẻ, mỗi thẻ được phân tách bằng dấu phẩy. Ví dụ:

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

Để hiển thị tất cả các đầu vào và đầu ra TensorInfo cho một SignatureDef cụ thể, hãy chuyển trong khóa SignatureDef cho tùy chọn signature_def . Điều này rất hữu ích khi bạn muốn biết giá trị khóa ten, dtype và hình dạng của các tenx đầu vào để thực hiện biểu đồ tính toán sau này. Ví dụ:

 $ 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
 

Để hiển thị tất cả thông tin có sẵn trong SavingModel, hãy sử dụng tùy chọn --all . Ví dụ:

$ 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 lệnh

Gọi lệnh run để chạy tính toán đồ thị, chuyển các đầu vào và sau đó hiển thị (và tùy chọn lưu) các đầu ra. Đây là cú pháp:

 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]
 

Lệnh run cung cấp ba cách sau để truyền đầu vào cho mô hình:

  • Tùy chọn --inputs cho phép bạn vượt qua ndarray numpy trong các tệp.
  • Tùy chọn --input_exprs cho phép bạn chuyển các biểu thức Python.
  • Tùy chọn --input_examples cho phép bạn vượt qua tf.train.Example .

--inputs

Để truyền dữ liệu đầu vào trong tệp, chỉ định tùy chọn --inputs , có định dạng chung sau:

 --inputs <INPUTS>
 

trong đó INPUTS là một trong các định dạng sau:

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

Bạn có thể vượt qua nhiều INPUTS . Nếu bạn vượt qua nhiều đầu vào, hãy sử dụng dấu chấm phẩy để phân tách từng INPUTS .

saved_model_cli sử dụng numpy.load để tải tên tệp . Tên tệp có thể ở bất kỳ định dạng nào sau đây:

  • .npy
  • .npz
  • định dạng dưa chua

Một tập tin .npy luôn chứa một ndarray numpy. Do đó, khi tải từ tệp .npy , nội dung sẽ được gán trực tiếp cho .npy đầu vào được chỉ định. Nếu bạn chỉ định một variable_name với điều đó .npy tập tin, các variable_name sẽ bị bỏ qua và cảnh báo sẽ được phát hành.

Khi tải từ một .npz file (zip), bạn có thể tùy chọn chỉ định một variable_name để xác định các biến bên trong file zip để tải cho phím tensor đầu vào. Nếu bạn không chỉ định một variable_name, các SavedModel CLI sẽ kiểm tra rằng chỉ có một tập tin được bao gồm trong các tập tin zip và tải nó cho phím tensor đầu vào quy định.

Khi tải từ tệp dưa, nếu không có variable_name được chỉ định trong dấu ngoặc vuông, bất cứ thứ gì có trong tệp dưa sẽ được chuyển đến khóa tenor đầu vào đã chỉ định. Nếu không, SavedModel CLI sẽ cho rằng một cuốn từ điển được lưu trữ trong file dưa và giá trị tương ứng với variable_name sẽ được sử dụng.

--input_exprs

Để chuyển các đầu vào thông qua các biểu thức Python, chỉ định tùy chọn --input_exprs . Điều này có thể hữu ích khi bạn không có các tệp dữ liệu nằm xung quanh, nhưng vẫn muốn kiểm tra mô hình với một số đầu vào đơn giản phù hợp với kiểu chữ và hình dạng của SignatureDef của mô hình. Ví dụ:

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

Ngoài các biểu thức Python, bạn cũng có thể truyền các hàm numpy. Ví dụ:

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

(Lưu ý rằng mô-đun numpy đã có sẵn cho bạn dưới dạng np .)

--input_examples

Để vượt qua tf.train.Example làm đầu vào, chỉ định tùy chọn --input_examples . Đối với mỗi khóa đầu vào, nó sẽ lấy một danh sách từ điển, trong đó mỗi từ điển là một thể hiện của tf.train.Example . Các khóa từ điển là các tính năng và các giá trị là danh sách giá trị cho từng tính năng. Ví dụ:

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

Lưu đầu ra

Theo mặc định, CLI SavingModel ghi đầu ra vào thiết bị xuất chuẩn. Nếu một thư mục được chuyển đến tùy chọn --outdir , các đầu ra sẽ được lưu dưới dạng các tệp .npy được đặt tên theo các .npy đầu ra trong thư mục đã cho.

Sử dụng --overwrite để ghi đè lên các tệp đầu ra hiện có.