本笔记参照TensorFlow官方教程,主要是对‘Save a model-Training checkpoints’教程内容翻译和内容结构编排,原文链接:Using the SavedModel format

文章目录

  • 一、用Keras创建‘已保存模型’(Creating a SavedModel form Keras)
  • 二、在TensorFlow Serving里运行一个‘已保存模型’(SavedModel)
  • 三、硬盘上‘已保存模型’的格式(The SavedModel format on disk)
  • 四、输出自定义模型(Exporting custom models)
  • 五、用Python重新使用‘已保存模型’(Reusing SavedModels in Python)
    • 5.1 基本的微调(Basic fine-tuning)
    • 5.2 一般的微调(General fine-tuning)
  • 六、‘已保存模型’中的控制流(Control flow in SavedModels)
  • 七、用Estimator保存模型(SavedModels from Extimators)
  • 八、用C++加载‘已保存模型’(Load a SavedModel in C++)
  • 九、‘已保存模型’的命令行交互细节(Detais of the SavedModel command line interface)
    • 9.1 安装‘已保存模型’CLI(Install the SavedModel CLI)
    • 9.2 命令概览
    • 9.3 ‘show’命令
    • 9.4 运行(run)命令
    • 9.5 保存输出

注意:‘已保存模型’含有整个TensorFlow程序,包含权重和计算。它并不需要原始的模型代码,这样很适合分享和部署(部署到TFLite,TensorFlow.js,TensorFlow Serving,或TensorFlow Hub)。

如果你有Python代码写的模型,并且只想加载权重,那可以设置检查点,详情参考:guide to training checkpoints


一、用Keras创建‘已保存模型’(Creating a SavedModel form Keras)

为了快速介绍,本节导出一个预先训练好的Keras模型,并使用它来处理图像分类请求。指南的其余部分将详细介绍并讨论创建savedmodel的其他方法。

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np
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


我们将使用‘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)
print()decoded = imagenet_labels[np.argsort(result_before_save)[0,::-1][:5]+1]print("Result before saving:\n", decoded)
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.6/mobilenet_1_0_224_tf.h5
17227776/17225924 [==============================] - 1s 0us/stepResult before saving:['military uniform' 'bow tie' 'suit' 'bearskin' 'pickelhaube']

这张图片的最高预测是‘军服’

tf.saved_model.save(pretrained_model, "/tmp/mobilenet/1/")
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1781: 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/mobilenet/1/assets

保存路径遵循TensorFlow Serving使用的约定,其中最后一个路径组件(这里是1/)是模型的版本号——它允许TensorFlow Serving这样的工具来推断相对的新鲜度。

SavedModel有一个命名函数叫‘Signatures’。Keras模型在serving_default签名密钥下导出它们的前向传递。SavedModel命令行接口对于检查磁盘上的SavedModels很有用:

!saved_model_cli show --dir /tmp/mobilenet/1 --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):inputs['input_1'] tensor_info:dtype: DT_FLOATshape: (-1, 224, 224, 3)name: serving_default_input_1:0
The given SavedModel SignatureDef contains the following output(s):outputs['act_softmax'] tensor_info:dtype: DT_FLOATshape: (-1, 1000)name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict

我们可以用tf.saved_model.load将‘SavedModel’加载回Python,观察‘Admiral Hopper’的图像是如何被分类的。

loaded = tf.saved_model.load("/tmp/mobilenet/1/")
print(list(loaded.signatures.keys()))  # ["serving_default"]
['serving_default']

导入的签名总是返回字典。

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

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

二、在TensorFlow Serving里运行一个‘已保存模型’(SavedModel)

SavedModels可以从Python中使用(更多信息见下面),但是生产环境通常使用专用的服务进行推理,而不运行Python代码。这很容易通过使用‘TensorFlow Serving’从‘SavedModel’中设置。

有关服务的更多细节,请参阅:TensorFlow Serving REST tutorial包括在笔记本或本地计算机上安装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"])

预测的结果与Python的结果相同。

三、硬盘上‘已保存模型’的格式(The SavedModel format on disk)

SavedModel是一个包含序列化签名和运行这些签名所需的状态的目录,包括变量值和词汇表。

!ls /tmp/mobilenet/1
assets  saved_model.pb  variables

saved_model.pb文件存储了实际的TensorFlow程序或模型,以及一组命名的签名,每个签名标识一个接受张量输入并产生张量输出的函数。
‘SavedModel’可能包含模型的多个变体(多个v1.MetaGraphDefs,用–tag_set标志来标识saved_model_cil),但是这种情况很少见。创建模型的多个变体的api包括tf.Estimator.experimental_export_all_saved_models和TensorFlow 1.x 中的tf.saved_model.Builder。

!saved_model_cli show --dir /tmp/mobilenet/1 --tag_set serve
The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
SignatureDef key: "__saved_model_init_op"
SignatureDef key: "serving_default"

变量目录包含一个标准的训练检查点(参考学习笔记16)

!ls /tmp/mobilenet/1/variables
variables.data-00000-of-00002  variables.data-00001-of-00002  variables.index

assets目录包含TensorFlow图使用的文件,例如用于初始化词汇表的文本文件。在本例中未使用它。
SavedModels可能有一个‘assets.extra’目录,用来记录没有被TensorFlow图使用的文件,例如为使用者提供关于如何处理SavedModel的信息。TensorFlow本身并不使用这个目录。

四、输出自定义模型(Exporting custom models)

在第一节,‘tf.saved_model.save’自动决定了用于‘tf.keras.Model’对象的签名。这是因为Keras模型有一个明确的方法来导出和形状(shapes)已知的输入。用低级别的模型创建API也能让‘tf.saved_model.save’工作,但如果打算为模型提供服务,则需要指出使用哪个函数作为签名。

class CustomModule(tf.Module):def __init__(self):super(CustomModule, self).__init__()self.v = tf.Variable(1.)@tf.functiondef __call__(self, 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.function装饰的方法。而这些函数将包含在SavedModel中,如果通过tf.saved_model.load将‘SavedModel’重新加载到Python程序中,不显示地声明服务签名工具(如TensorFlow Serving和saved_model_cli)就不能访问他们。
‘mutate’方法有一个声明过的‘input_signature’,因此在SavedModel中已经有足够的信息来保存它的计算图。'call’方法没有声明过的签名,因此它的签名是在保存之前从它的使用方式中推断出来的:调用该方法一次或多次将为参数可见的张量形状(shape)和dtypes的每个特定组合创建计算图。

module(tf.constant(0.))
tf.saved_model.save(module, "/tmp/module_no_signatures")
INFO:tensorflow:Assets written to: /tmp/module_no_signatures/assets

对于没有input_signature的函数,在保存之前使用的任何输入形状在加载之后都是可用的。因为我们只使用了标量调用了‘call’方法,所以它只接受标量值。

imported = tf.saved_model.load("/tmp/module_no_signatures")
assert 3. == imported(tf.constant(3.)).numpy()
imported.mutate(tf.constant(2.))
assert 6. == imported(tf.constant(3.)).numpy()

这个函数将不接受向量:

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

‘get_concrete_function’让我们不需要调用函数,就可以往函数里添加输入形状。它需要‘tf.TensorSpec’对象来取代Tensor参数,表示输入的形状(shapes)和dtypes。‘形状’可以为‘None’,表示任何形状都可以,或者表示一个轴(axis)大小的列表。如果轴(axis)大小为‘None’,那这个轴(axis)可以接受任何大小。(这个常被用于批大小(batch size))我们也可以给‘tf.TensorSpec’取名,默认情况下为函数参数的关键字(以下为‘x’)

module.__call__.get_concrete_function(x=tf.TensorSpec([None], tf.float32))
tf.saved_model.save(module, "/tmp/module_no_signatures")
imported = tf.saved_model.load("/tmp/module_no_signatures")
assert [3.] == imported(tf.constant([3.])).numpy()
INFO:tensorflow:Assets written to: /tmp/module_no_signatures/assets

我们没有将导出的函数标识为签名,所以它没有。

!saved_model_cli show --dir /tmp/module_no_signatures --tag_set serve
The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
SignatureDef key: "__saved_model_init_op"

4.1标识输出签名(Identifying a signature to export)
要指出一个函数应该是签名,请在保存时指定签名参数。

call = module.__call__.get_concrete_function(tf.TensorSpec(None, tf.float32))
tf.saved_model.save(module, "/tmp/module_with_signature", signatures=call)
INFO:tensorflow:Assets written to: /tmp/module_with_signature/assets
 注意:我们第一次用‘get_concrete_function’将‘tf.function’转换为‘ConcreteFunction’。这是必要的,因为函数是在没有固定的input_signature的情况下创建的,因此没有与之相关的一组确定的张量输入。
!saved_model_cli show --dir /tmp/module_with_signature --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):inputs['x'] tensor_info:dtype: DT_FLOATshape: unknown_rankname: serving_default_x:0
The given SavedModel SignatureDef contains the following output(s):outputs['output_0'] tensor_info:dtype: DT_FLOATshape: unknown_rankname: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict
imported = tf.saved_model.load("/tmp/module_with_signature")
signature = imported.signatures["serving_default"]
assert [3.] == signature(x=tf.constant([3.]))["output_0"].numpy()
imported.mutate(tf.constant(2.))
assert [6.] == signature(x=tf.constant([3.]))["output_0"].numpy()
assert 2. == imported.v.numpy()

我们导出了一个签名,其密钥默认为“serving_default”。要导出多个签名,请传递一个字典。

@tf.function(input_signature=[tf.TensorSpec([], tf.string)])
def parse_string(string_input):return imported(tf.strings.to_number(string_input))signatures = {"serving_default": parse_string,"from_float": imported.signatures["serving_default"]}tf.saved_model.save(imported, "/tmp/module_with_multiple_signatures", signatures)
INFO:tensorflow:Assets written to: /tmp/module_with_multiple_signatures/assets
!saved_model_cli show --dir /tmp/module_with_multiple_signatures --tag_set serve
The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
SignatureDef key: "__saved_model_init_op"
SignatureDef key: "from_float"
SignatureDef key: "serving_default"

用‘saved_model_cli’可以从命令行直接运行‘SavedModel’

!saved_model_cli run --dir /tmp/module_with_multiple_signatures --tag_set serve --signature_def serving_default --input_exprs="string_input='3.'"
!saved_model_cli run --dir /tmp/module_with_multiple_signatures --tag_set serve --signature_def from_float --input_exprs="x=3."
2019-10-08 01:03:58.756878: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2019-10-08 01:03:58.763375: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.764046: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1618] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:05.0
2019-10-08 01:03:58.764312: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:03:58.765636: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10.0
2019-10-08 01:03:58.766994: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10.0
2019-10-08 01:03:58.767300: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10.0
2019-10-08 01:03:58.768874: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10.0
2019-10-08 01:03:58.770021: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10.0
2019-10-08 01:03:58.773585: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2019-10-08 01:03:58.773693: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.774186: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.774586: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1746] Adding visible gpu devices: 0
2019-10-08 01:03:58.774854: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
2019-10-08 01:03:58.781107: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2000189999 Hz
2019-10-08 01:03:58.781693: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x530c040 executing computations on platform Host. Devices:
2019-10-08 01:03:58.781724: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version
2019-10-08 01:03:58.867097: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.867624: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x530df00 executing computations on platform CUDA. Devices:
2019-10-08 01:03:58.867654: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Tesla V100-SXM2-16GB, Compute Capability 7.0
2019-10-08 01:03:58.867828: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.868302: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1618] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:05.0
2019-10-08 01:03:58.868362: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:03:58.868377: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10.0
2019-10-08 01:03:58.868386: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10.0
2019-10-08 01:03:58.868397: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10.0
2019-10-08 01:03:58.868427: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10.0
2019-10-08 01:03:58.868439: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10.0
2019-10-08 01:03:58.868453: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2019-10-08 01:03:58.868540: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.868976: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.869357: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1746] Adding visible gpu devices: 0
2019-10-08 01:03:58.869401: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:03:58.870402: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1159] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-10-08 01:03:58.870426: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1165]      0
2019-10-08 01:03:58.870437: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1178] 0:   N
2019-10-08 01:03:58.870554: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.870982: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:03:58.871384: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1304] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 6849 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/tools/saved_model_cli.py:339: load (from tensorflow.python.saved_model.loader_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.loader.load or tf.compat.v1.saved_model.load. There will be a new function for importing SavedModels in Tensorflow 2.0.
Result for output key output_0:
6.0
2019-10-08 01:04:01.666328: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2019-10-08 01:04:01.672683: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.673132: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1618] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:05.0
2019-10-08 01:04:01.673331: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:04:01.674645: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10.0
2019-10-08 01:04:01.675852: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10.0
2019-10-08 01:04:01.676166: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10.0
2019-10-08 01:04:01.677709: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10.0
2019-10-08 01:04:01.678883: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10.0
2019-10-08 01:04:01.682458: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2019-10-08 01:04:01.682565: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.683041: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.683469: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1746] Adding visible gpu devices: 0
2019-10-08 01:04:01.683760: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
2019-10-08 01:04:01.690090: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2000189999 Hz
2019-10-08 01:04:01.690722: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x564b9b0 executing computations on platform Host. Devices:
2019-10-08 01:04:01.690750: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Host, Default Version
2019-10-08 01:04:01.777802: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.778326: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x564d870 executing computations on platform CUDA. Devices:
2019-10-08 01:04:01.778358: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): Tesla V100-SXM2-16GB, Compute Capability 7.0
2019-10-08 01:04:01.778567: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.779037: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1618] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:05.0
2019-10-08 01:04:01.779102: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:04:01.779122: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10.0
2019-10-08 01:04:01.779138: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcufft.so.10.0
2019-10-08 01:04:01.779156: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcurand.so.10.0
2019-10-08 01:04:01.779174: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusolver.so.10.0
2019-10-08 01:04:01.779192: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcusparse.so.10.0
2019-10-08 01:04:01.779220: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudnn.so.7
2019-10-08 01:04:01.779297: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.779765: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.780205: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1746] Adding visible gpu devices: 0
2019-10-08 01:04:01.780258: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2019-10-08 01:04:01.781294: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1159] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-10-08 01:04:01.781320: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1165]      0
2019-10-08 01:04:01.781329: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1178] 0:   N
2019-10-08 01:04:01.781448: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.781878: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1006] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-10-08 01:04:01.782327: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1304] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 6849 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/tools/saved_model_cli.py:339: load (from tensorflow.python.saved_model.loader_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.loader.load or tf.compat.v1.saved_model.load. There will be a new function for importing SavedModels in Tensorflow 2.0.
Result for output key output_0:
6.0

五、用Python重新使用‘已保存模型’(Reusing SavedModels in Python)

让我们再看看上面的‘CustomModule’类,以及这种类型的模块对象是如何作为SavedModels保存并加载回来的。是否注意到在没有使用签名的情况下调用了module(…)?

在派生自‘tf.keras.Model’或‘tf.Model’对象上调用‘tf.saved_model.save(obj,’/path’)’,将‘tf.Variable’的属性保存为‘obj’,递归地遍历其属性引用的对象,以及保存在这些对象上发现的变量属性的当前值。同样,这些对象上的‘tf.function-decorated’方法保存了它们的计算图。然而,原始的Python类型,Python方法代码和‘Python-valued’的数据成员丢失了。

调用‘obj=tf.saved_model.load(’/path’)'方法来恢复已保存的对象(现在简化为占位符类型),它们的变量属性以及各自保存的值,以及它们的‘tf.function’装饰方法。只要保存了一个包含张量形状和非张量值组合的计算图,就可以像以前一样调用这些方法。重新在Python代码里跟踪‘tf.function’将不可能,并且会产生异常。

恢复的‘tf.function’可以提供比在‘.signatures’字典里的具体函数更丰富的Python化的API给恢复的模型。然而,对于依靠签名的非Python环境,这些API是不可用的。

5.1 基本的微调(Basic fine-tuning)

 变量对象是可用的,我们可以导入函数来进行后向传播。这样对于简单场景下的‘SavedModel’微调(fine-tuning)已经足够了。
optimizer = tf.optimizers.SGD(0.05)def train_step():with tf.GradientTape() as tape:loss = (10. - imported(tf.constant(2.))) ** 2variables = 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 0print("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

5.2 一般的微调(General fine-tuning)

 Keras的‘SavedModel’提供了比普通的‘__call__’更多的细节来处理更高级的微调场景。TensorFlow Hub建议在共享的SavedModels中提供以下功能(如果适用),以便进行微调:- 如果模型使用丢弃(dropout)或前向传递在训练和推理之间有所不同的其它技术(如批处理正则化batch normalization),则使用‘__call__’方法,其中‘Python-valued’'training='参数默认为False,可以被设置为‘True’。- 除了‘__call__’属性,还有‘.variable’和‘.trainable_variable’属性与变量列表相关联。'.trainable_variables'中省略了一个原本是可训练的变量,但在微调期间将其冻结。- 对于像Keras这样将权重调整器表示为层或子模型属性的框架,还可以有一个.regularization_losses属性。它包含一个零参数函数的列表,这些函数的值是用来增加总损失的。回到MobileNet初始化,我们可以看到这些动作:
loaded = tf.saved_model.load("/tmp/mobilenet/1/")
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.variablesif 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, ...

六、‘已保存模型’中的控制流(Control flow in SavedModels)

 任何可以进入‘tf.function’的东西也可以进入‘SavedModel’。对于包括依赖于张量的条件逻辑的‘AutoGraph’,由常规Python控制流指定。
@tf.function(input_signature=[tf.TensorSpec([], tf.int32)])
def control_flow(x):if x < 0:tf.print("Invalid!")else:tf.print(x % 3)to_export = tf.Module()
to_export.control_flow = control_flow
tf.saved_model.save(to_export, "/tmp/control_flow")
INFO:tensorflow:Assets written to: /tmp/control_flow/assets
imported = tf.saved_model.load("/tmp/control_flow")
imported.control_flow(tf.constant(-1))  # Invalid!
imported.control_flow(tf.constant(2))   # 2
imported.control_flow(tf.constant(3))   # 0
Invalid!
2
0

七、用Estimator保存模型(SavedModels from Extimators)

 Estimator通过‘tf.Estimator.export_saved_model’导出‘SavedModels’。更多详情参看学习笔记9。
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]))
export_path = estimator.export_saved_model("/tmp/from_estimator/", serving_input_fn)
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmp9qiqjm1c
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp9qiqjm1c', '_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': <tensorflow.python.training.server_lib.ClusterSpec object at 0x7f10599bab00>, '_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_core/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_core/python/feature_column/feature_column_v2.py:518: Layer.add_variable (from tensorflow.python.keras.engine.base_layer) 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_estimator/python/estimator/canned/linear.py:308: to_float (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.cast` instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/keras/optimizer_v2/ftrl.py:143: 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:Saving checkpoints for 0 into /tmp/tmp9qiqjm1c/model.ckpt.
INFO:tensorflow:loss = 0.6931472, step = 0
INFO:tensorflow:Saving checkpoints for 50 into /tmp/tmp9qiqjm1c/model.ckpt.
INFO:tensorflow:Loss for final step: 0.3829868.
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_core/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/tmp9qiqjm1c/model.ckpt-50
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: /tmp/from_estimator/temp-b'1570496648'/saved_model.pb

这种SavedModel接受序列化‘tf.Example’协议缓存,这对服务是有用的。但我们可以用’tf.saved_model.load’加载它并用Python运行它。

imported = tf.saved_model.load(export_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))
{'class_ids': <tf.Tensor: id=55292, shape=(1, 1), dtype=int64, numpy=array([[1]])>, 'classes': <tf.Tensor: id=55293, shape=(1, 1), dtype=string, numpy=array([[b'1']], dtype=object)>, 'all_class_ids': <tf.Tensor: id=55290, shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>, 'all_classes': <tf.Tensor: id=55291, shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: id=55294, shape=(1, 1), dtype=float32, numpy=array([[0.56012416]], dtype=float32)>, 'probabilities': <tf.Tensor: id=55296, shape=(1, 2), dtype=float32, numpy=array([[0.43987584, 0.56012416]], dtype=float32)>, 'logits': <tf.Tensor: id=55295, shape=(1, 1), dtype=float32, numpy=array([[0.24166596]], dtype=float32)>}
{'class_ids': <tf.Tensor: id=55300, shape=(1, 1), dtype=int64, numpy=array([[0]])>, 'classes': <tf.Tensor: id=55301, shape=(1, 1), dtype=string, numpy=array([[b'0']], dtype=object)>, 'all_class_ids': <tf.Tensor: id=55298, shape=(1, 2), dtype=int32, numpy=array([[0, 1]], dtype=int32)>, 'all_classes': <tf.Tensor: id=55299, shape=(1, 2), dtype=string, numpy=array([[b'0', b'1']], dtype=object)>, 'logistic': <tf.Tensor: id=55302, shape=(1, 1), dtype=float32, numpy=array([[0.2347819]], dtype=float32)>, 'probabilities': <tf.Tensor: id=55304, shape=(1, 2), dtype=float32, numpy=array([[0.76521814, 0.2347819 ]], dtype=float32)>, 'logits': <tf.Tensor: id=55303, shape=(1, 1), dtype=float32, numpy=array([[-1.1815039]], dtype=float32)>}

‘tf.estimator.export.build_raw_serving_input_receiver_fn’允许我们用原始张量(raw tensors)而不是‘tf.train.Example’创建输入函数。

八、用C++加载‘已保存模型’(Load a SavedModel in C++)

 C++版本的SavedModel加载器提供了一个从路径加载SavedModel的API,同时运行‘SessionOptions’和‘RunOptions’。我们需要指定关联被加载图的标签(tags)。SavedModel的加载版本被称为SavedModelBundle,它包含MetaGraphDef和加载它的会话。
const string export_dir = ...
SavedModelBundle bundle;
...
LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain},&bundle);

九、‘已保存模型’的命令行交互细节(Detais of the SavedModel command line interface)

 我们可以用SavedModel命令交互界面去检查和执行一个SavedModel。例如,我们可以用CLI(Command Line Interface)去检查模型的‘SignatureDef’。CLI让我们可以快速的确认输入张量的形状和dtype是否和模型匹配。并且,如果我们想测试我们的模型,我们可以使用CLI来进行全面检查(sanity check),方法是传入各种格式的示例输入(例如Python表达式),然后获得输出。

9.1 安装‘已保存模型’CLI(Install the SavedModel CLI)

 一般来说,我们可以通过以下两种方式安装TensorFlow:- 通过安装预构建的TensorFlow二进制文件 - 通过从源代码构建TensorFlow。如果我们通过预构建的TensorFlow二进制文件安装TensorFlow,那SavedModel CLI已经安装到我们系统里了,路径名为bin/saved_model_cli。如果我们从源代码构建TensorFlow,那我们必须通过下面额外的命令来创建‘saved_model_cli’:
$ bazel build tensorflow/python/tools:saved_model_cli

9.2 命令概览

 SavedModel CLI支持下面两种命令:- ‘show’,显示‘SavedModel’里可用的计算- ‘run’,运行‘SavedModel’里的计算

9.3 ‘show’命令

 一个SavedModel含有一个或多个模型变体(v1.MetaGraphDefs),由它们的标记集来标识。为了服务模型,我们可能会好奇每个模型变体里有哪种‘SignatureDef’,它们的输入和输出是什么。‘show’命令允许我们按层次顺序检查SavedModel的内容。这里的语法:
usage: saved_model_cli show [-h] --dir DIR [--all]
[--tag_set TAG_SET] [--signature_def SIGNATURE_DEF_KEY]

例如,下面的命令显示了所有SavedModel里可用的标记集(tag-sets):

$ 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

要显示特定SignatureDef的所有输入和输出TensorInfo,请将SignatureDef键传递给signature_def选项。当你想要知道张量的键值,输入张量的类型和形状,以便以后执行计算图形时,这是非常有用的。例如:

$ 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_FLOATshape: (-1, 1)name: x:0
The given SavedModel SignatureDef contains the following output(s):outputs['y'] tensor_info:dtype: DT_FLOATshape: (-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_FLOATshape: (-1, 1)name: x2:0The given SavedModel SignatureDef contains the following output(s):outputs['scores'] tensor_info:dtype: DT_FLOATshape: (-1, 1)name: y3:0Method name is: tensorflow/serving/classify...signature_def['serving_default']:The given SavedModel SignatureDef contains the following input(s):inputs['x'] tensor_info:dtype: DT_FLOATshape: (-1, 1)name: x:0The given SavedModel SignatureDef contains the following output(s):outputs['y'] tensor_info:dtype: DT_FLOATshape: (-1, 1)name: y:0Method name is: tensorflow/serving/predict

9.4 运行(run)命令

 调用run命令来运行图形计算,传递输入,然后显示(可选保存)输出。这里的语法:
usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_defSIGNATURE_DEF_KEY [--inputs INPUTS][--input_exprs INPUT_EXPRS][--input_examples INPUT_EXAMPLES] [--outdir OUTDIR][--overwrite] [--tf_debug]

‘run’命令提供下面三种方法将输入传递给模型:
- ‘–inputs’选项让我们可以传递文件里的‘numpy ndarry’
- ‘–input_exprs’选项让我们可以传递Python表达
- ‘–input_example’选项让我们可以传递‘tf.train.Example’。

–inputs:为了传递文件里的数据,需要指定‘–inputs’选项,它需要遵守下面的通用格式:

--inputs <INPUTS>

也可以是下面的格式:

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

我们可以传递多个输入。如果传递多个输入,则使用分号分隔每个输入。
‘saved_model_cli’用‘numpy.load’来加载文件名。文件名可以是下面任何一种格式:‘.npy’、‘.npz’、‘pickle format’

‘.npy’文件通常包含一个‘numpy ndarray’。因此,当从‘.npy’文件加载时,内容将被直接分配给指定的输入张量。如果我们使用.npy文件指定了variable_name,那么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’选项。当我们没有数据文件,但是仍然想要用一些简单的输入来检查模型,这些输入与模型的SignatureDefs的dtype和shape匹配时,这是非常有用的。例如:

`<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"]}]`

9.5 保存输出

 默认情况下,SavedModel CLI将输出写入stdout。如果将目录传递给——outdir选项,则输出将保存为给定目录下以输出张量键命名的.npy文件。使用‘--overwrite’来覆盖现有的输出的文件

TensorFlow2.0 Guide官方教程 学习笔记17 -‘Using the SavedModel format‘相关推荐

  1. TensorFlow2.0 Guide官方教程 学习笔记20 -‘Effective TensorFlow 2‘

    本笔记参照TensorFlow Guide官方教程,主要是对'Effictive TensorFlow 2'教程内容翻译和内容结构编排,原文链接:Effictive TensorFlow 2 高效的T ...

  2. TensorFlow2.0 Guide官方教程 学习笔记10- Eager execution

    本笔记参照TensorFlow官方教程,主要是对'Eager execution'教程内容翻译和内容结构编排,原文链接:Eager execution 目录 一.创建环境和基本使用 二.动态控制流 三 ...

  3. 【从零开始的大数据学习】Flink官方教程学习笔记(一)

    Flink官方教程学习笔记 学习资源 基础Scala语法 Scala数据结构专题 声明变量 代码块 函数(function) 方法(methods) Traits (接口) class(类) tupl ...

  4. Dynamic Quantization PyTorch官方教程学习笔记

    诸神缄默不语-个人CSDN博文目录 本文是PyTorch的教程Dynamic Quantization - PyTorch Tutorials 1.11.0+cu102 documentation的学 ...

  5. 【网络教程】Iptables官方教程-学习笔记5--IPTABLES MATCH

    这篇博客介绍iptables和netfilter中所有可用的匹配,章节比较厂,没必要去学习每个匹配的具体细节,大致了解下即可,后续要用到再深入掌握它. 一 .Iptables 的匹配(match) 在 ...

  6. 【网络教程】IPtables官方教程--学习笔记3

    一.遍历表和链 本节我们将讨论信息包如何遍历不同的链(chains)以及以什么样的顺序.我们也会讨论表(tables)的遍历顺序,以及研究与内核相关的某些其它组件所涉及的问题,也就是说不同的路由决策等 ...

  7. Ceres Solver 官方教程学习笔记(十二)——非线性最小二乘法建模Modeling Non-linear Least Squares (下)

    这一部分主要是最后的Problem比较重要. 带条件的代价函数ConditionedCostFunction 这个类使用户可以在使用封装好的代价函数的同时,对残差值加入一定的条件限制.举个例子,现在已 ...

  8. Opencv4 -Python官方教程学习笔记33---BRIEF

    理论 我们知道SIFT使用128维矢量作为描述符.由于它使用浮点数,因此基本上需要512个字节.同样,SURF最少也需要256个字节(用于64像素).为数千个功能部件创建这样的向量会占用大量内存,这对 ...

  9. PCL学习笔记(二):PCL官方教程学习

    PCL学习笔记(二):PCL官方教程学习 PCD文件制作 Features 表面法线提取 Keypoints 提取NARF关键点 KdTree Range Image How to create a ...

最新文章

  1. LeetCode Maximum XOR of Two Numbers in an Array(贪心、字典树)
  2. 【软件期刊01】2017-02-22
  3. C语言scanf函数的返回值、scanf函数的安全版、在while条件中使用scanf函数
  4. Kotlin的基本数值类型问题:是对象?还是基本数据类型?
  5. spoj Longest Common Substring II
  6. 来说一说你对锁都怎么分类?
  7. MSP430程序跑飞原因
  8. tf.layers.dense
  9. xp和linux的引导文件,Linux与XP双系统中grub引导配置笔记
  10. c#窗口操作-句柄操控全解
  11. animate.css在vue项目中的使用
  12. Nginx核心原理揭秘:Nginx为什么高效?
  13. 【PIL】Image中blend的简单使用
  14. python 基于滑动平均思想实现缺失数据填充
  15. 【数据结构】顺序线性表的几种常用方法
  16. JanusGraph
  17. R语言中ggplot Theme Assist安装使用教程
  18. There's code using JDBC based datastore and not disposing them和threadLocal多次访问时,有的时候会访问不到
  19. matlabsvd提取特征值_MATLAB中的SVD函数
  20. SwiftUI+CoreData项目出现The operation couldn’t be completed(GenericObjCError error 0)错误的解决

热门文章

  1. 高德地图:弧度飞线图层详解
  2. mysql参数化查询 in_mysql in 查询参数化
  3. 分别用雅可比(Jacobi)迭代法和高斯—塞德尔(Gauss—Seidel)迭代法求解线性方程组
  4. 【兴趣】儿时背诵过的朝代歌和节气歌
  5. 手机输入法emoji、颜文字存储
  6. 广告过滤算法实现及优化
  7. 浙江杭州一男子网恋1年求见面, 开门一看这美女长得像“李逵”
  8. FFmpeg源码分析:AVIOContext、IO模型与协议
  9. for key in file_keys
  10. OpenStack组件部署之Placement