หน้านี้ได้รับการแปลโดย 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 ระดับต่ำ:

การสร้าง SavedModel จาก Keras

สำหรับการแนะนำอย่างรวดเร็วส่วนนี้ส่งออกโมเดล Keras ที่ผ่านการฝึกอบรมมาล่วงหน้าและให้บริการคำขอการจัดประเภทรูปภาพด้วย ส่วนที่เหลือของคำแนะนำจะกรอกรายละเอียดและหารือเกี่ยวกับวิธีอื่น ๆ ในการสร้าง SavedModels

 import os
import tempfile

from matplotlib import pyplot as plt
import numpy as np
import tensorflow as tf

tmpdir = tempfile.mkdtemp()
 
 physical_devices = tf.config.experimental.list_physical_devices('GPU')
if physical_devices:
  tf.config.experimental.set_memory_growth(physical_devices[0], True)
 
 file = tf.keras.utils.get_file(
    "grace_hopper.jpg",
    "https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg")
img = tf.keras.preprocessing.image.load_img(file, target_size=[224, 224])
plt.imshow(img)
plt.axis('off')
x = tf.keras.preprocessing.image.img_to_array(img)
x = tf.keras.applications.mobilenet.preprocess_input(
    x[tf.newaxis,...])
 
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg
65536/61306 [================================] - 0s 0us/step

PNG

เราจะใช้รูปภาพของ Grace Hopper เป็นตัวอย่างการรันและรูปแบบการจัดหมวดหมู่รูปภาพที่ฝึกอบรมมาก่อนของ Keras เนื่องจากใช้งานง่าย โมเดลที่กำหนดเองก็ใช้งานได้เช่นกันและจะกล่าวถึงรายละเอียดในภายหลัง

 labels_path = tf.keras.utils.get_file(
    'ImageNetLabels.txt',
    'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
imagenet_labels = np.array(open(labels_path).read().splitlines())
 
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt
16384/10484 [==============================================] - 0s 0us/step

 pretrained_model = tf.keras.applications.MobileNet()
result_before_save = pretrained_model(x)

decoded = imagenet_labels[np.argsort(result_before_save)[0,::-1][:5]+1]

print("Result before saving:\n", decoded)
 
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/mobilenet/mobilenet_1_0_224_tf.h5
17227776/17225924 [==============================] - 1s 0us/step
Result before saving:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

คำทำนายที่ดีที่สุดสำหรับภาพนี้คือ "เครื่องแบบทหาร"

 mobilenet_save_path = os.path.join(tmpdir, "mobilenet/1/")
tf.saved_model.save(pretrained_model, mobilenet_save_path)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: /tmp/tmpmjpd1j0o/mobilenet/1/assets

save-path เป็นไปตามแบบแผนที่ใช้โดย TensorFlow Serving โดยที่คอมโพเนนต์ path สุดท้าย ( 1/ ที่นี่) เป็นหมายเลขเวอร์ชันสำหรับรุ่นของคุณ - ช่วยให้เครื่องมือเช่น Tensorflow Serving ให้เหตุผลเกี่ยวกับความสดใหม่ของสัมพัทธ์

เราสามารถโหลด SavedModel กลับสู่ Python ด้วย tf.saved_model.load และดูว่ารูปภาพของ Admiral Hopper นั้นถูกจัดประเภทอย่างไร

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

ลายเซ็นที่นำเข้าจะส่งคืนพจนานุกรมเสมอ ในการปรับแต่งชื่อลายเซ็นต์และคีย์พจนานุกรมเอาท์พุทดู การระบุลายเซ็นระหว่างการส่งออก

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

การอนุมานที่ทำงานอยู่จาก SavedModel ให้ผลลัพธ์เช่นเดียวกับรุ่นดั้งเดิม

 labeling = infer(tf.constant(x))[pretrained_model.output_names[0]]

decoded = imagenet_labels[np.argsort(labeling)[0,::-1][:5]+1]

print("Result after saving and loading:\n", decoded)
 
Result after saving and loading:
 ['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

การเรียกใช้ SavedModel ใน TensorFlow 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 นั้นเหมือนกับผลลัพธ์จาก Python

รูปแบบ 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 s พบผ่านทางข้าม recursive จะถูกบันทึกไว้ (ดูที่ บทช่วยสอน เกี่ยวกับการสำรวจเส้นทางสำรวจแบบเรียกซ้ำ) อย่างไรก็ตามคุณลักษณะของ Python, ฟังก์ชั่นและข้อมูลใด ๆ จะสูญหายไป ซึ่งหมายความว่าเมื่อบันทึก tf.function จะไม่มีการบันทึกรหัส Python

หากไม่มีการบันทึกรหัส Python SavedModel จะรู้วิธีเรียกคืนฟังก์ชันได้อย่างไร

สั้น ๆ tf.function ทำงานโดยติดตามรหัส Python เพื่อสร้าง ConcreteFunction (wrapper callable รอบ tf.Graph ) เมื่อบันทึก tf.function คุณกำลังบันทึกแคชของ Concretefunctions ของ tf.function จริง ๆ

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับความสัมพันธ์ระหว่าง 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 s มีการบูรณะในโครงสร้างวัตถุเหมือนกับต้นฉบับที่บันทึกไว้ tf.Module

 imported = tf.saved_model.load(module_no_signatures_path)
assert imported(tf.constant(3.)).numpy() == 3
imported.mutate(tf.constant(2.))
assert imported(tf.constant(3.)).numpy() == 6
 

เนื่องจากไม่มีการบันทึกรหัส Python การเรียกใช้ tf.function ด้วยลายเซ็นอินพุตใหม่จะล้มเหลว:

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

การปรับจูนแบบพื้นฐาน

มีวัตถุที่มีตัวแปรและเราสามารถ backprop ผ่านฟังก์ชั่นที่นำเข้า นั่นก็เพียงพอแล้วที่จะปรับแต่ง 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__ ธรรมดาเพื่อ __call__ กับกรณีและปัญหาที่ละเอียดกว่า TensorFlow Hub แนะนำให้จัดทำสิ่งต่อไปนี้หากมีการใช้ร่วมกันใน SavedModels เพื่อวัตถุประสงค์ในการปรับแต่ง:

  • หากโมเดลใช้ดรอปเอาท์หรือเทคนิคอื่นซึ่งพาสพาสด์แตกต่างระหว่างการฝึกอบรมและการอนุมาน (เช่นการทำให้เป็นมาตรฐานเป็นชุด) เมธอด __call__ จะใช้อาร์กิวเมนต์ Python- __call__ training= อาร์กิวเมนต์ที่เป็นค่าเริ่มต้นเป็น False แต่สามารถตั้งค่าเป็น True
  • ถัดจากแอตทริบิวต์ __call__ จะมีแอตทริบิวต์. .variable และ. .trainable_variable พร้อมรายการตัวแปรที่เกี่ยวข้อง ตัวแปรที่ แต่เดิมฝึกอบรมได้ แต่ตั้งใจจะถูกแช่แข็งในระหว่างการปรับจูนจะถูกละเว้นจาก. .trainable_variables
  • เพื่อประโยชน์ของเฟรมเวิร์กเช่น Keras ที่แสดงน้ำหนัก regularizers เป็นคุณลักษณะของเลเยอร์หรือโมเดลย่อยนอกจากนี้ยังสามารถมีแอตทริบิวต์. .regularization_losses มันถือรายการของฟังก์ชั่นศูนย์อาร์กิวเมนต์ที่มีค่ามีความหมายสำหรับนอกเหนือไปจากการสูญเสียทั้งหมด

กลับไปที่ตัวอย่าง MobileNet เริ่มต้นเราสามารถเห็นบางส่วนของการกระทำ:

 loaded = tf.saved_model.load(mobilenet_save_path)
print("MobileNet has {} trainable variables: {}, ...".format(
          len(loaded.trainable_variables),
          ", ".join([v.name for v in loaded.trainable_variables[:5]])))
 
MobileNet has 83 trainable variables: conv1/kernel:0, conv1_bn/gamma:0, conv1_bn/beta:0, conv_dw_1/depthwise_kernel:0, conv_dw_1_bn/gamma:0, ...

 trainable_variable_ids = {id(v) for v in loaded.trainable_variables}
non_trainable_variables = [v for v in loaded.variables
                           if id(v) not in trainable_variable_ids]
print("MobileNet also has {} non-trainable variables: {}, ...".format(
          len(non_trainable_variables),
          ", ".join([v.name for v in non_trainable_variables[:3]])))
 
MobileNet also has 54 non-trainable variables: conv1_bn/moving_mean:0, conv1_bn/moving_variance:0, conv_dw_1_bn/moving_mean:0, ...

การระบุลายเซ็นต์ระหว่างการส่งออก

เครื่องมือเช่น TensorFlow การให้บริการและการ saved_model_cli สามารถโต้ตอบกับ SavedModels เพื่อช่วยเครื่องมือเหล่านี้พิจารณาว่าฟังก์ชั่นการใช้งานของฟังก์ชั่นคอนกรีตใดเราต้องระบุลายเซ็นการแสดงผล tf.keras.Model s ระบุลายเซ็นการแสดงโดยอัตโนมัติ แต่เราจะต้องประกาศลายเซ็นการให้บริการสำหรับโมดูลที่กำหนดเองของเราอย่างชัดเจน

ตามค่าเริ่มต้นจะไม่มีการประกาศลายเซ็นต์ใน 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 ของคุณเพื่อส่งคืนพจนานุกรมที่แม็พชื่อเอาต์พุตกับเอาต์พุต ชื่อของอินพุตได้มาจากชื่อฟังก์ชั่น Python

 class CustomModuleWithOutputName(tf.Module):
  def __init__(self):
    super(CustomModuleWithOutputName, self).__init__()
    self.v = tf.Variable(1.)

  @tf.function(input_signature=[tf.TensorSpec([], tf.float32)])
  def __call__(self, x):
    return {'custom_output_name': x * self.v}

module_output = CustomModuleWithOutputName()
call_output = module_output.__call__.get_concrete_function(tf.TensorSpec(None, tf.float32))
module_output_path = os.path.join(tmpdir, 'module_with_output_name')
tf.saved_model.save(module_output, module_output_path,
                    signatures={'serving_default': call_output})
 
INFO:tensorflow:Assets written to: /tmp/tmpmjpd1j0o/module_with_output_name/assets

 imported_with_output_name = tf.saved_model.load(module_output_path)
imported_with_output_name.signatures['serving_default'].structured_outputs
 
{'custom_output_name': TensorSpec(shape=(), dtype=tf.float32, name='custom_output_name')}

SavedModels จากเครื่องมือประมาณการ

เครื่องมือประมาณการส่งออก SavedModels ผ่าน tf.Estimator.export_saved_model ดู คำแนะนำเกี่ยวกับเครื่องมือประมาณการ สำหรับรายละเอียด

 input_column = tf.feature_column.numeric_column("x")
estimator = tf.estimator.LinearClassifier(feature_columns=[input_column])

def input_fn():
  return tf.data.Dataset.from_tensor_slices(
    ({"x": [1., 2., 3., 4.]}, [1, 1, 0, 0])).repeat(200).shuffle(64).batch(16)
estimator.train(input_fn)

serving_input_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn(
  tf.feature_column.make_parse_example_spec([input_column]))
estimator_base_path = os.path.join(tmpdir, 'from_estimator')
estimator_path = estimator.export_saved_model(estimator_base_path, serving_input_fn)
 
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmp65c02lsq
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp65c02lsq', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/feature_column/feature_column_v2.py:540: Layer.add_variable (from tensorflow.python.keras.engine.base_layer_v1) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/ftrl.py:144: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp65c02lsq/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 0.6931472, step = 0
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 50...
INFO:tensorflow:Saving checkpoints for 50 into /tmp/tmp65c02lsq/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 50...
INFO:tensorflow:Loss for final step: 0.4131384.
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/saved_model/signature_def_utils_impl.py:145: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info.
INFO:tensorflow:Signatures INCLUDED in export for Classify: ['serving_default', 'classification']
INFO:tensorflow:Signatures INCLUDED in export for Regress: ['regression']
INFO:tensorflow:Signatures INCLUDED in export for Predict: ['predict']
INFO:tensorflow:Signatures INCLUDED in export for Train: None
INFO:tensorflow:Signatures INCLUDED in export for Eval: None
INFO:tensorflow:Restoring parameters from /tmp/tmp65c02lsq/model.ckpt-50
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: /tmp/tmpmjpd1j0o/from_estimator/temp-1594862628/saved_model.pb

SavedModel นี้ยอมรับบัฟเฟอร์โปรโตคอล tf.Example ทำให้เป็นอนุกรมซึ่งมีประโยชน์สำหรับการให้บริการ แต่เราสามารถโหลดด้วย tf.saved_model.load และเรียกใช้จาก Python

 imported = tf.saved_model.load(estimator_path)

def predict(x):
  example = tf.train.Example()
  example.features.feature["x"].float_list.value.extend([x])
  return imported.signatures["predict"](
    examples=tf.constant([example.SerializeToString()]))
 
 print(predict(1.5))
print(predict(3.5))
 
{'all_classes': <tf.Tensor: shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.5451435]], dtype=float32)>, 'probabilities': <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.45485654, 0.5451435 ]], dtype=float32)>, 'logits': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.18106687]], dtype=float32)>, 'class_ids': <tf.Tensor: shape=(1, 1), dtype=int64, numpy=array([[1]])>, 'classes': <tf.Tensor: shape=(1, 1), dtype=string, numpy=array([[b'1']], dtype=object)>, 'all_class_ids': <tf.Tensor: shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>}
{'all_classes': <tf.Tensor: shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[0.21604054]], dtype=float32)>, 'probabilities': <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.7839595 , 0.21604055]], dtype=float32)>, 'logits': <tf.Tensor: shape=(1, 1), dtype=float32, numpy=array([[-1.2888912]], dtype=float32)>, 'class_ids': <tf.Tensor: shape=(1, 1), dtype=int64, numpy=array([[0]])>, 'classes': <tf.Tensor: shape=(1, 1), dtype=string, numpy=array([[b'0']], dtype=object)>, 'all_class_ids': <tf.Tensor: shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>}

tf.estimator.export.build_raw_serving_input_receiver_fn ช่วยให้คุณสามารถสร้างฟังก์ชั่นการป้อนข้อมูลที่ใช้เทนเซอร์ดิบแทน tf.train.Example s

โหลด SavedModel ใน C ++

เวอร์ชัน C ++ ของตัว โหลด SavedModel จัดเตรียม API เพื่อโหลด SavedModel จากพา ธ ขณะที่อนุญาต SessionOptions และ RunOptions คุณต้องระบุแท็กที่เกี่ยวข้องกับกราฟที่จะโหลด รุ่นที่โหลดของ SavedModel เรียกว่า SavedModelBundle และมี MetaGraphDef และเซสชันที่โหลดอยู่

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

รายละเอียดของอินเตอร์เฟสบรรทัดคำสั่ง SavedModel

คุณสามารถใช้ SavedModel Command Line Interface (CLI) เพื่อตรวจสอบและดำเนินการ SavedModel ตัวอย่างเช่นคุณสามารถใช้ CLI เพื่อตรวจสอบ SignatureDef ของโมเดล CLI ช่วยให้คุณยืนยันได้อย่างรวดเร็วว่าอินพุต Tensor dtype และรูปร่างตรงกับรุ่น ยิ่งไปกว่านั้นถ้าคุณต้องการทดสอบแบบจำลองของคุณคุณสามารถใช้ CLI เพื่อทำการตรวจสอบสติได้โดยผ่านอินพุตตัวอย่างในรูปแบบต่าง ๆ (เช่นนิพจน์ Python) จากนั้นดึงเอาท์พุท

ติดตั้ง SavedModel CLI

โดยทั่วไปคุณสามารถติดตั้ง TensorFlow ได้สองวิธีดังต่อไปนี้:

  • โดยการติดตั้งไบนารี TensorFlow ที่สร้างไว้ล่วงหน้า
  • โดยการสร้าง TensorFlow จากซอร์สโค้ด

หากคุณติดตั้ง TensorFlow ผ่านไบนารี TensorFlow ที่สร้างไว้ล่วงหน้าแล้ว SavedModel CLI จะถูกติดตั้งบนระบบของคุณแล้วที่ pathname bin/saved_model_cli

หากคุณสร้าง TensorFlow จากซอร์สโค้ดคุณต้องรันคำสั่งเพิ่มเติมต่อไปนี้เพื่อสร้าง saved_model_cli :

 $ bazel build tensorflow/python/tools:saved_model_cli
 

ภาพรวมของคำสั่ง

SavedModel CLI สนับสนุนคำสั่งสองคำสั่งต่อไปนี้บน SavedModel:

  • show ซึ่งแสดงการคำนวณที่มีอยู่ใน SavedModel
  • run ซึ่งรันการคำนวณจาก SavedModel

show คำสั่ง

SavedModel มีหนึ่งรุ่นที่แตกต่างกันของโมเดล (ในทางเทคนิค, v1.MetaGraphDef s), ระบุโดยชุดแท็ก ในการให้บริการแบบจำลองคุณอาจสงสัยว่า SignatureDef s ประเภทใดในแต่ละรุ่นและสิ่งที่เป็นอินพุทและเอาท์พุท คำสั่ง show ให้คุณตรวจสอบเนื้อหาของ SavedModel ตามลำดับชั้น นี่คือไวยากรณ์:

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

ตัวอย่างเช่นคำสั่งต่อไปนี้แสดงชุดแท็กที่มีอยู่ทั้งหมดใน SavedModel:

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

คำสั่งต่อไปนี้แสดงกุญแจ SignatureDef มีอยู่ทั้งหมดสำหรับชุดแท็ก:

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

หากมี หลาย แท็กในชุดแท็กคุณต้องระบุแท็กทั้งหมดโดยแต่ละแท็กคั่นด้วยเครื่องหมายจุลภาค ตัวอย่างเช่น:

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

ในการแสดงอินพุตและเอาต์พุต TensorInfo ทั้งหมดสำหรับ SignatureDef ระบุให้ส่งผ่านตัวเลือก SignatureDef ไปที่ signature_def สิ่งนี้มีประโยชน์มากเมื่อคุณต้องการทราบค่าคีย์เทนเซอร์, 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 คำสั่ง 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 ช่วยให้คุณสามารถผ่านลำดับ 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 มักจะมี narry ndarray อยู่เสมอ ดังนั้นเมื่อโหลดจากไฟล์. .npy เนื้อหาจะถูกกำหนดให้กับเทนเซอร์อินพุตที่ระบุโดยตรง หากคุณระบุ variable_name ด้วยไฟล์. .npy นั้น variable_name จะถูกละเว้นและจะมีการออกคำเตือน

เมื่อทำการโหลดจาก .npz (zip) คุณอาจเลือกระบุ variable_name เพื่อระบุตัวแปรภายในไฟล์ zip ที่จะโหลดสำหรับคีย์เทนเซอร์ หากคุณไม่ได้ระบุ variable_name SavedModel CLI จะตรวจสอบว่ามีไฟล์เพียงไฟล์เดียวเท่านั้นที่รวมอยู่ในไฟล์ zip และโหลดสำหรับคีย์เมตริกซ์อินพุตที่ระบุ

เมื่อโหลดจากไฟล์ pickle หากไม่ได้ระบุ variable_name ไว้ในวงเล็บเหลี่ยมสิ่งใดก็ตามที่อยู่ภายในไฟล์ pickle จะถูกส่งผ่านไปยังคีย์เทนเซอร์ มิฉะนั้น SavedModel CLI จะถือว่าพจนานุกรมถูกเก็บไว้ในไฟล์ pickle และค่าที่สอดคล้องกับ variable_name จะถูกใช้

--input_exprs

ในการส่งอินพุตผ่านนิพจน์ Python ให้ระบุตัวเลือก --input_exprs สิ่งนี้มีประโยชน์เมื่อคุณไม่มีไฟล์ข้อมูลวางอยู่รอบ ๆ แต่ยังต้องการตรวจสอบรุ่นด้วยอินพุตง่าย ๆ ที่ตรงกับ dtype และรูปร่างของ SignatureDef ของโมเดล ตัวอย่างเช่น:

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

นอกเหนือจากการแสดงออกของ Python คุณอาจผ่านฟังก์ชั่น 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 เขียนทับไฟล์ที่ส่งออกที่มีอยู่