可重用 SavedModel
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
简介
TensorFlow Hub 用于托管 TensorFlow 2 的 SavedModel 等资产。开发者可以使用 obj = hub.load(url)
将这些资产重新加载到 Python 程序中 [了解详情]。返回的 obj
为 tf.saved_model.load()
的结果(请参阅 TensorFlow 的 SavedModel 指南)。此对象可以具有任意特性,包括 tf.functions、tf.Variables(从其预训练值初始化)、其他资源,以及递归地包含更多此类对象。
本页将介绍在 TensorFlow Python 程序中重用资源而需要通过加载的 obj
实现的接口。符合此类接口条件的 SavedModel 称为可重用 SavedModel。
“重用”意味着围绕 obj
构建更大的模型,并且应当能够进行微调。微调意味着进一步训练作为周围模型一部分的加载 obj
中的权重。损失函数和优化器由周围模型确定;obj
仅定义输入到输出激活的映射(“前向传递”),可能包括诸如随机失活或批次归一化之类的技术。
按照上述概念,对于所有要重用的 SavedModel,TensorFlow Hub 团队均建议实现可重用 SavedModel 接口。tensorflow_hub
库中的许多实用工具(特别是 hub.KerasLayer
)都需要 SavedModel 来实现。
与 SignatureDef 的关系
就 tf.functions 和其他 TF2 功能而言,此接口与 SavedModel 的签名不同,后者自 TF1 时期便可用,并沿用到 TF2 中用于推断(例如将 SavedModels 部署到 TF Serving 或 TF Lite)。推断的签名的表达力不够充分,不支持微调,而 tf.function
为重用模型提供了更自然和更具表达力的 Python API。
与模型构建库的关系
可重用 SavedModel 仅使用 TensorFlow 2 基元,与任何特定的模型构建库(例如 Keras 或 Sonnet)无关。这有助于在模型构建库间重用,而无需依赖原始模型构建代码。
将可重用 SavedModel 加载到任何给定模型构建库或从这些模型构建库保存 SavedModel,都需要进行一些调整。对于 Keras,hub.KerasLayer 提供加载,Keras 中以 SavedModel 格式保存的内置功能已针对 TF2 重新设计,旨在提供此接口的超集(请参阅 2019 年 5 月的 RFC)。
与任务特定的“常用 SavedModel API”的关系
此页面上的接口定义允许任何数量和类型的输入和输出。TF Hub 的常用 SavedModel API 使用用法惯例针对特定任务优化了此通用接口,使模型可以轻松地互换。
接口定义
特性
可重用 SavedModel 为 TensorFlow 2 SavedModel,obj = tf.saved_model.load(...)
将返回具有以下特性的对象:
__call__
:必选。实现模型计算(“前向传递”)的 tf.function,遵循以下规范。
variables
:tf.Variable 对象列表,列出了 __call__
的任何可能调用使用的所有变量,包括可训练和不可训练变量。
如果为空,则可省略此列表。
注:为方便记录,在加载 TF1 SavedModel 以表示其 GLOBAL_VARIABLES
集合时,此名称与 tf.saved_model.load(...)
合成的特性一致。
trainable_variables
:v.trainable
对于所有元素均为 true 的 tf.Variable 对象列表。这些变量必须是 variables
的子集。它们是微调对象时要训练的变量。SavedModel 创建者在此可以选择省略一些最初可训练的变量,以表明在微调期间不应修改这些变量。
如果为空,则可省略此列表,特别是当 SavedModel 不支持微调时。
regularization_losses
:tf.function 列表,其中的每个函数均接受零输入并返回单个标量浮点张量。为了进行微调,建议 SavedModel 用户将这些函数作为附加正则化项包括在损失中(在最简单的情况下,无需进一步缩放)。通常,它们用于表示权重正则化器。(由于缺少输入,这些 tf.function 无法表达激活正则化器。)
如果为空,则可省略此列表,特别是当 SavedModel 不支持微调或不希望规定权重正则化时。
__call__
函数
恢复的 SavedModel obj
具有 obj.__call__
特性,为恢复的 tf.function,支持按以下方式调用 obj
。
Synopsis(伪代码):
outputs = obj(inputs, trainable=..., **kwargs)
参数
参数如下。
有一个位置必选参数,其中包含 SavedModel 的一批输入激活。类型为以下三者之一:
- 单个张量,针对单个输入;
- 张量列表,针对未命名输入的有序序列;
- 张量字典,由一组特定输入名称键控。
(此接口的未来修订版本可能支持更多的常规嵌套。)SavedModel 创建者选择其中一种类型,并选择张量形状和数据类型。如果适用,不应定义形状的某些维度(尤其是批次大小)。
有一项可选的关键字参数 training
,该参数接受 Python 布尔值 True
或 False
。默认值为 False
。如果模型支持微调,并且其计算在两者(例如,随机失活和批次归一化)之间有所不同,则可以使用此参数实现该区别。否则,可以不使用此参数。
__call__
不必接受张量值 training
参数。如果有必要,则由调用者使用 tf.cond()
在它们之间进行调度。
SavedModel 创建者可以选择接受更多具有特定名称的可选 kwargs
。
对于张量值参数,SavedModel 创建者可定义其允许的数据类型和形状。tf.function
接受在使用 tf.TensorSpec 输入跟踪的参数上使用 Python 默认值。此类参数可用于自定义 __call__
中涉及的数字超参数(例如,随机失活率)。
对于 Python 值参数,SavedModel 创建者可定义其允许的值。此类参数可用作标志,在跟踪函数中进行离散选择(但要注意跟踪记录的组合爆炸式增长)。
恢复的 __call__
函数必须提供对所有允许的参数组合的跟踪记录。在 True
与 False
之间切换 training
不得改变参数的容许性。
结果
调用 obj
所得的 outputs
可以是:
- 单个张量,针对单个输出;
- 张量列表,针对未命名输出的有序序列;
- 张量字典,由一组特定输出名称键控。
(此接口的未来修订版本可能支持更多的常规嵌套。)返回类型可能会因 Python 值关键字参数而异。这样可以考虑产生额外输出的标志。SavedModel 创建者定义输出数据类型和形状及其对输入的依赖。
命名可调用对象
按照上述方式,可重用 SavedModel 可以通过放入命名子对象(例如 obj.foo
、obj.bar
等)来提供多个模型部分。每个子对象提供一个 __call__
方法,并支持特定于该模型部分的变量等方面的特性。对于上述示例,将包括 obj.foo.__call__
、obj.foo.variables
等。
请注意,此接口不涵盖直接将裸 tf.function 添加为 tf.foo
的方式。
可重用 SavedModel 的用户只应处理一级嵌套 (obj.bar
,而非 obj.bar.baz
)。(此接口的未来修订版本可能支持更深层的嵌套,并且可能放弃对顶级对象本身可调用的要求。)
结束语
与进程中 API 的关系
本文档介绍了由 tf.function 和 tf.Variable 等基元组成的 Python 类的接口,这些基元通过 tf.saved_model.save()
和 tf.saved_model.load()
执行序列化和反序列化。但是,传递给 tf.saved_model.save()
的原始对象已经具有该接口。适配该接口可以在单个 TensorFlow 程序中实现跨建模 API 交换模型部分。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2022-09-21。
[null,null,["最后更新时间 (UTC):2022-09-21。"],[],[],null,["# Reusable SavedModels\n\n\u003cbr /\u003e\n\nIntroduction\n------------\n\nTensorFlow Hub hosts SavedModels for TensorFlow 2, among other assets.\nThey can be loaded back into a Python program with `obj = hub.load(url)`\n\\[[learn more](/hub/tf2_saved_model)\\]. The returned `obj` is the result\nof [`tf.saved_model.load()`](https://www.tensorflow.org/api_docs/python/tf/saved_model/load) (see TensorFlow's\n[SavedModel guide](https://www.tensorflow.org/guide/saved_model)).\nThis object can have arbitrary attributes that are tf.functions,\ntf.Variables (initialized from their pre-trained values), other resources\nand, recursively, more such objects.\n\nThis page describes an interface to be implemented by the loaded `obj`\nin order to be *reused* in a TensorFlow Python program.\nSavedModels conforming to this interface are called *Reusable SavedModels*.\n\nReusing means building a larger model around `obj`, including the ability\nto fine-tune it. Fine-tuning means further training of the weights in the loaded\n`obj` as part of the surrounding model. The loss function and the\noptimizer are determined by the surrounding model; `obj` only defines\nthe mapping of input to output activations (the \"forward pass\"), possibly\nincluding techniques such as dropout or batch normalization.\n\n**The TensorFlow Hub team recommends implementing the Reusable SavedModel\ninterface** in all SavedModels that are meant to be reused in the above sense.\nMany utilities from the `tensorflow_hub` library, notably [`hub.KerasLayer`](https://www.tensorflow.org/hub/api_docs/python/hub/KerasLayer),\nrequire SavedModels to implement it.\n\n### Relation to SignatureDefs\n\nThis interface in terms of tf.functions and other TF2 features\nis separate from the SavedModel's signatures, which have been\navailable since TF1 and continue to be used in TF2 for inference\n(such as deploying SavedModels to TF Serving or TF Lite).\nSignatures for inference are not expressive enough to support fine-tuning,\nand [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function)\nprovides a more natural and expressive\n[Python API](https://www.tensorflow.org/tutorials/customization/performance)\nfor the reused model.\n\n### Relation to model-building libraries\n\nA Reusable SavedModel uses only TensorFlow 2 primitives, independent of any\nparticular model-building library like Keras or Sonnet. This facilitates reuse\nacross model-building libraries, free from dependencies on the original\nmodel-building code.\n\nSome amount of adaptation will be needed load Reusable SavedModels into or save\nthem from any given model-building library. For Keras,\n[hub.KerasLayer](https://www.tensorflow.org/hub/api_docs/python/hub/KerasLayer)\nprovides the loading, and Keras's built-in saving in the SavedModel format has\nbeen redesigned for TF2 with the goal of providing a superset of this interface\n(see the\n[RFC](https://github.com/tensorflow/community/blob/master/rfcs/20190509-keras-saved-model.md)\nfrom May 2019).\n\n### Relation to task-specific \"Common SavedModel APIs\"\n\nThe interface definition on this page allows for any number and type of inputs\nand outputs. The\n[Common SavedModel APIs for TF Hub](/hub/common_saved_model_apis) refine\nthis general interface with usage conventions for specific tasks to make models\neasily interchangeable.\n\nInterface definition\n--------------------\n\n### Attributes\n\nA Reusable SavedModel is a TensorFlow 2 SavedModel such that\n`obj = tf.saved_model.load(...)` returns an object that has the following\nattributes\n\n- `__call__`. Required. A tf.function implementing the model's computation\n (the \"forward pass\") subject to the specification below.\n\n- `variables`: A list of tf.Variable objects, listing all the variables\n used by any possible invocation of `__call__`, including both\n trainable and non-trainable ones.\n\n This list can be omitted if empty.\n | **Note:** Conveniently, this name coincides with the attribute synthesized by [`tf.saved_model.load(...)`](https://www.tensorflow.org/api_docs/python/tf/saved_model/load) when loading a TF1 SavedModel to represent its `GLOBAL_VARIABLES` collection.\n- `trainable_variables`: A list of tf.Variable objects such that\n `v.trainable` is true for all elements.\n These variables must be a subset of `variables`.\n These are the variables to be trained when fine-tuning the object.\n The SavedModel creator may choose to omit some variables here that were\n originally trainable to indicate that these should not be modified during\n fine-tuning.\n\n This list can be omitted if empty, in particular, if the SavedModel does not\n support fine-tuning.\n- `regularization_losses`: A list of tf.functions, each taking zero inputs\n and returning a single scalar float tensor. For fine-tuning, the\n SavedModel user is advised to include these as additional regularization\n terms into the loss (in the simplest case without further scaling).\n Typically, these are used to represent weight regularizers.\n (For lack of inputs, these tf.functions cannot express\n activity regularizers.)\n\n This list can be omitted if empty, in particular, if the SavedModel does not\n support fine-tuning or does not wish to prescribe weight regularization.\n\n### The `__call__` function\n\nA Restored SavedModel `obj` has an `obj.__call__` attribute that is\na restored tf.function and allows `obj` to be called as follows.\n\nSynopsis (pseudo-code): \n\n outputs = obj(inputs, trainable=..., **kwargs)\n\n#### Arguments\n\nThe arguments are as follows.\n\n- There is one positional, required argument with a batch of input activations\n of the SavedModel. Its type is one of\n\n - a single Tensor for a single input,\n - a list of Tensors for an ordered sequence of unnamed inputs,\n - a dict of Tensors keyed by a particular set of input names.\n\n (Future revisions of this interface may allow more general nests.)\n The SavedModel creator chooses one of those and the tensor shapes\n and dtypes. Where useful, some dimensions of the shape should be\n undefined (notably batch size).\n- There may be an optional keyword argument `training` that accepts a Python\n boolean, `True` or `False`. The default is `False`.\n If the model supports fine-tuning, and if its computation differs between\n the two (e.g., as in dropout and batch normalization), that distinction\n is implemented with this argument. Otherwise, this argument may be absent.\n\n It is not required that `__call__` accept a Tensor-valued `training`\n argument. It falls on the caller to use [`tf.cond()`](https://www.tensorflow.org/api_docs/python/tf/cond) if necessary\n to dispatch between them.\n- The SavedModel creator may choose to accept more optional `kwargs`\n of particular names.\n\n - For Tensor-valued arguments, the SavedModel creator defines their\n permissible dtypes and shapes. [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function) accepts a Python default\n value on an argument that is traced with a tf.TensorSpec input.\n Such arguments can be used to allow customization of numeric\n hyperparameters involved in `__call__` (e.g., dropout rate).\n\n - For Python-valued arguments, the SavedModel creator defines their\n permissible values. Such arguments can be used as flags to make\n discrete choices in the traced function (but mind the combinatorial\n explosion of traces).\n\nThe restored `__call__` function must provide traces for all permissible\ncombinations of arguments. Flipping `training` between `True` and `False`\nmust not change the permissibility of arguments.\n\n#### Result\n\nThe `outputs` from calling `obj` can be\n\n- a single Tensor for a single output,\n- a list of Tensors for an ordered sequence of unnamed outputs,\n- a dict of Tensors keyed by a particular set of output names.\n\n(Future revisions of this interface may allow more general nests.)\nThe return type may vary depending on the Python-valued kwargs.\nThis allows for flags producing extra outputs.\nThe SavedModel creator defines the output dtypes and shapes and their\ndependency on inputs.\n\n### Named callables\n\nA Reusable SavedModel can provide multiple model pieces in the way\ndescribed above by putting them into named subobjects, for example,\n`obj.foo`, `obj.bar` and so on.\nEach subobject provides a `__call__` method and supporting attributes\nabout the variables etc. specific to that model piece.\nFor the example above, there would be `obj.foo.__call__`,\n`obj.foo.variables` and so on.\n\nNote that this interface does *not* cover the approach of adding\na bare tf.function directly as `tf.foo`.\n\nUsers of Reusable SavedModels are only expected to handle one level of nesting\n(`obj.bar` but not `obj.bar.baz`). (Future revisions of this interface may allow\ndeeper nesting, and may waive the requirement that the top-level object be\ncallable itself.)\n\nClosing remarks\n---------------\n\n### Relation to in-process APIs\n\nThis document describes an interface of a Python class which consists\nof primitives like tf.function and tf.Variable that survive a\nround-trip through serialization via [`tf.saved_model.save()`](https://www.tensorflow.org/api_docs/python/tf/saved_model/save)\nand [`tf.saved_model.load()`](https://www.tensorflow.org/api_docs/python/tf/saved_model/load). However, the interface was already present\non the original object that was passed to [`tf.saved_model.save()`](https://www.tensorflow.org/api_docs/python/tf/saved_model/save).\nAdaptation to that interface enables the exchange of model pieces\nacross model-building APIs within a single TensorFlow program."]]