此页面由 Cloud Translation API 翻译。
Switch to English

TF1集线器格式

TensorFlow Hub在2018年发布时提供了一种资产类型:TF1 Hub格式,可导入TensorFlow 1程序。

本页说明如何将TF1中的TF1集线器格式(或TF2的TF1兼容模式)与hub.Module类和关联的API一起使用。 (典型的使用是要建立一个tf.Graph ,可能内部的TF1 Estimator ,由一个或多个模型与TF1集线器格式组合tf.compat.layerstf.layers )。

TensorFlow 2(在TF1兼容模式之外)的用户必须将新API与hub.load()hub.KerasLayer 。新的API会加载新的TF2 SavedModel资产类型,但对将TF1集线器格式加载到TF2中的支持有限。

使用TF1 Hub格式的模型

以TF1集线器格式实例化模型

通过从具有URL或文件系统路径的字符串中创建hub.Module对象,将TF1 Hub格式的模型导入TensorFlow程序,例如:

 m = hub.Module("path/to/a/module_dir")
 

这会将模块的变量添加到当前的TensorFlow图中。运行其初始化程序将从磁盘读取其预训练的值。同样,表和其他状态也会添加到图形中。

缓存模块

通过URL创建模块时,模块内容将下载并缓存在本地系统临时目录中。可以使用TFHUB_CACHE_DIR环境变量来覆盖模块的缓存位置。有关详细信息,请参见缓存

应用模块

一旦实例化,模块m可以被调用零次或多次,就像从张量输入到张量输出的Python函数一样:

 y = m(x)
 

每个此类调用将操作添加到当前TensorFlow图以从x计算y 。如果这涉及具有经过训练的权重的变量,则这些变量将在所有应用程序之间共享。

模块可以定义多个命名签名 ,以允许以多种方式应用(类似于Python对象具有方法 )。模块的文档应描述可用的签名。上面的调用将应用名为"default"的签名。可以通过将名称传递给可选的signature=参数来选择任何签名。

如果签名具有多个输入,则必须将其作为字典传递,并使用签名定义的密钥。同样,如果签名具有多个输出,则可以通过在签名定义的键下传递as_dict=True ,将as_dict=True作为dict检索(键"default"用于as_dict=False返回的单个输出)。因此,应用模块的最一般形式如下:

 outputs = m(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]
 

调用者必须提供签名定义的所有输入,但不要求使用模块的所有输出。 TensorFlow将仅运行模块的那些最终以tf.Session.run()中的目标依赖关系的部分。实际上,模块发布者可以选择提供各种输出以供高级使用(例如中间层的激活)以及主要输出。模块使用者应妥善处理其他输出。

试用替代模块

只要有多个模块可以执行同一任务,TensorFlow Hub就会鼓励为它们配备兼容的签名(接口),这样,尝试不同的签名就如同更改字符串值超参数一样容易。

为此,我们维护了针对常见任务的推荐通用签名集合。

创建一个新模块

相容性说明

TF1集线器格式适用于TensorFlow1。TensorFlow 2中的TF集线器仅部分支持它。请一定考虑使用新的TF2 SavedModel格式发布。

TF1集线器格式在语法层面上类似于TensorFlow 1的SavedModel格式(相同的文件名和协议消息),但在语义上有所不同,以允许模块重用,组合和重新训练(例如,资源初始化程序的不同存储,不同的标记)元符号惯例)。区分它们在磁盘上的最简单方法是tfhub_module.pb文件的存在与否。

一般的做法

要定义新模块,发布者使用功能module_fn调用hub.create_module_spec() 。此函数使用tf.placeholder()构造由调用者提供的输入的表示模块内部结构的图形。然后,它通过调用hub.add_signature(name, inputs, outputs)一次或多次来定义签名。

例如:

 def module_fn():
  inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
  layer1 = tf.layers.dense(inputs, 200)
  layer2 = tf.layers.dense(layer1, 100)
  outputs = dict(default=layer2, hidden_activations=layer1)
  # Add default signature.
  hub.add_signature(inputs=inputs, outputs=outputs)

...
spec = hub.create_module_spec(module_fn)
 

可以使用hub.create_module_spec()的结果hub.create_module_spec()而不是路径)来实例化特定TensorFlow图内的模块对象。在这种情况下,没有检查点,并且模块实例将使用变量初始值设定项代替。

任何模块实例都可以通过其export(path, session)方法序列化到磁盘。导出模块会将其定义以及session中其变量的当前状态序列化到传递的路径中。首次导出模块时以及导出微调模块时均可使用此功能。

为了与TensorFlow Estimators兼容, hub.LatestModuleExporter从最新的检查点导出模块,就像tf.estimator.LatestExporter从最新的检查点导出整个模型一样。

模块发布者应在可能的情况下实施通用签名 ,以便消费者可以轻松地交换模块并找到解决问题的最佳方法。

真实的例子

查看我们的文本嵌入模块导出器 ,以获取有关如何从通用文本嵌入格式创建模块的真实示例。

微调

训练导入模块的变量及其周围模型的变量称为微调 。微调可以提高质量,但会增加新的复杂性。我们建议消费者只有在探索了更简单的质量调整之后,并且只有在模块发布者推荐的情况下,才进行微调。

对于消费者

要启用微调,请使用hub.Module(..., trainable=True)实例化模块以使其变量可训练并导入TensorFlow的REGULARIZATION_LOSSES 。如果模块具有多个图形变体,请确保选择一个适合训练的变体。通常,这就是带有标签{"train"}标签。

选择一种不会破坏预训练权重的训练方案,例如,比从头开始训练的学习率要低。

对于出版商

为了使消费者更容易进行微调,请注意以下几点:

  • 微调需要正规化。你的模块输出与REGULARIZATION_LOSSES集合,这是什么使你的选择tf.layers.dense(..., kernel_regularizer=...)等成什么样的消费者从获得tf.losses.get_regularization_losses()最好采用这种方式来定义L1 / L2正则化损失。

  • 在发布者模型中,避免通过tf.train.FtrlOptimizertf.train.ProximalGradientDescentOptimizer和其他邻近优化器的l1_l2_regularization_strength参数定义L1 / L2正则化。这些不会与模块一起导出,并且全局设置正则化强度可能不适合于使用者。除了在宽模型(即稀疏线性模型)或宽和深模型中的L1正则化之外,应该可以使用单个正则化损失代替。

  • 如果您使用辍学,批处理规范化或类似的训练技术,请将其超参数设置为对许多预期用途有意义的值。辍学率可能必须根据目标问题的过度拟合倾向进行调整。在批次归一化中,动量(aka衰减系数)应足够小,以便能够使用小数据集和/或大批次进行微调。对于高级消费者,请考虑添加一个签名,以暴露对关键超参数的控制。