原文:TensorFlow 2.0 的新功能 - 2019.01.16
出处:TensorFlow - 微信公众号
作者: Google TensorFlow 团队
TensorFlow 已经发展为世界上最受欢迎和被广泛采用的机器学习平台之一,我们衷心感谢一直以来支持我们的各界的开发者和他们的贡献:
2018 年 11 月,TensorFlow 迎来了它的 3 岁生日,我们回顾了几年来它增加的功能,进而对另一个重要里程碑 TensorFlow 2.0 感到兴奋 !
TensorFlow 2.0 将专注于 简单性 和 易用性,具有以下更新:
- 使用 Keras 和 eager execution,轻松构建模型
- 在任意平台上实现生产环境的稳健模型部署
- 为研究提供强大的实验工具
- 通过清理废弃的 API 和减少重复来简化 API
在过去的几年里,我们为 TensorFlow 添加了许多组件. 在 TensorFlow 2.0 中,它们将被打包成一个全面的平台,支持从训练到部署的机器学习工作流程. 让我们使用如下所示的简化概念图来了解 TensorFlow 2.0 的新架构:
注:上图的训练部分虽然侧重于 Python API,但 TensorFlow.js 也支持训练模型. 也支持其他语言,包括 Swift,R 和 Julia
1. 标准化 Keras:TensorFlow 2.0 高级 API 指南
Keras 是一个颇受欢迎的高级 API,专用于构建和训练深度学习模型. 此 API 可用于快速原型设计、顶尖研究与实际生产. TensorFlow 现已支持 Keras,但在 2.0 版中,我们正致力将 Keras 更紧密地集成至 TensorFlow 平台的其余组件.
通过将 Keras 打造为 TensorFlow 的高级 API,我们旨在帮助机器学习新手开发者们更轻松地开启 TensorFlow 入门之旅. 单个高级 API 可减少混淆,使我们更加专注于为研究人员提供高级功能.
Keras 具备以下几项关键优势:
- 人性化:Keras 界面简单、一致,已针对常见用例进行优化. Keras 能够就用户错误提供清晰且可处理的反馈,不仅便于用户了解错误消息,而且通常还能提供实用建议.
- 模块化与可组合性:Keras 模型由可配置的构建基块相连组合而成,几乎不存在任何限制. Keras 的部分组件可重复利用,用户将无需采用甚至了解框架提供的全部内容. 例如,无需通过 Keras 模型开展训练便可使用层或优化器.
- 易于扩展:可以通过编写自定义构建基块来展现新的研究思路,包括构建新层、损失函数等.
- 初学者和专家通用:深度学习开发者背景不同、经验水平各异,而无论您是刚刚入门,还是拥有多年经验,Keras 均可提供切合需求的 API.
综上所述,无论是学习机器学习、研究、应用开发抑或部署,Keras 均能在各类用例中简化工作流程并提高工作效率.
首先,我们会解答现已提出的几个问题. 其次,我们将深入了解 TensorFlow 随附的此版 Keras 将能实现哪些功能.
1.1. 常见问题解答
1.1.1. Keras 是否为一个独立的库?
其实,更应将 Keras 视为一种 API 规范.
Keras 的参考实现一直作为独立的开放源代码项目进行维护,具体可于此网站找到:www.keras.io. 该项目独立于 TensorFlow,并拥有一个活跃的贡献者与用户社区.
TensorFlow 包括 Keras API 的完整实现(位于 tf.keras 模块),且此 API 具备针对 TensorFlow 的增强功能.
1.1.2. Keras 只是 TensorFlow 或其他库的包装器吗?
不,这是一个常见误解(但可以理解).
Keras 是一种用于定义和训练机器学习模型的 API 标准.
Keras 与特定实现无关:Keras API 可用于 TensorFlow、MXNet、TypeScript、JavaScript、CNTK、Theano、PlaidML、Scala、CoreML 和其他库的实现.
1.1.3. TensorFlow 内置的 Keras 版本与 keras.io 提供的版本有何不同?
TensorFlow 包括 Keras API 的具体实现(位于 tf.keras 模块),且此 API 具备针对 TensorFlow 的增强功能. 这些功能包括:支持 Eager Execution 以便进行直观调试和快速迭代、支持 TensorFlow SavedModel 模型交换格式,以及为分布式训练(包括 TPU 上的训练)提供集成支持.
在使用 tf.keras Model Subclassing API 时,Eager Execution 功能尤为有用. 此 API 是受 Chainer 的启发开发而成,可命令式地编写模型的正向传递.
tf.keras 紧密集成于 TensorFlow 生态系统,同时也支持:
- tf.data:可构建高性能输入管道. 若您有意尝试,则可使用 NumPy 格式的数据训练模型,或使用 tf.data 来扩大规模和提升性能.
- 分布策略:该策略用于在各类计算配置中开展分布式训练,包括遍布于众多机器上的 GPU 和 TPU.
- 导出模型:利用 tf.keras API 创建的模型能够以 TensorFlow SavedModel 格式进行序列化,并能借助 TensorFlow Serving 或通过其他语言绑定(Java、Go、Rust、C# 等)提供给用户使用.
- 导出的模型可通过 TensorFlow Lite 部署至移动和嵌入式设备,同时也适用于 TensorFlow.js(注:也可使用同样常见的 Keras API 直接在 JavaScript 中开发模型).
- 特征列:用于有效表示及分类结构化数据.
- 此外,tf.keras 还可支持其他正在开发的内容.
1.2. tf.keras 的安装使用
tf.keras 内附于 TensorFlow 中. 您无需单独安装 Keras.
安装 tensorflow 或 tensorflow-gpu:
pip install tensorflow
pip install tensorflow-gpu
tf.keras 的使用:
import tensorflow as tf
Dense = tf.keras.layers.Dense
1.3. Sequential API
建议先从 tf.keras Sequential API 开始. 该 API 直观、简洁,且适用于实践中 95% 的机器学习问题. 使用此 API,大约只需 10 行代码便可编写出首个神经网络.
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
最常见的模型定义方法是构建层图,这与我们在深度学习中通常使用的心智模式相对应. 最简单的模型类型是层堆栈. 可以使用 Sequential API 定义此类模型,如下所示:
model = tf.keras.Sequential()
model.add(layers.Dense(64, activation=’relu’))
model.add(layers.Dense(64, activation=’relu’))
model.add(layers.Dense(10, activation=’softmax’))
Such a model can then be compiled and trained in a few lines:
model.compile(optimizer=’adam’,
loss=’sparse_categorical_crossentropy’,
metrics=[‘accuracy’])model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
更多 Sequential API 使用示例:tensorflow.org/tutorials
1.4. Functional API
当然,序贯模型只是简单的层堆栈,并不能表示任意模型.
可以使用 Functional API 构建更高级的模型,此 API 可帮助您定义复杂的拓扑结构,包括多输入和多输出模型、共享层模型以及采用残差连接的模型.
使用 Functional API 构建模型时,层可供调用(在张量上),还可返回张量以作为输出. 这些输入和输出张量可用于定义模型. 例如:
inputs = tf.keras.Input(shape=(32,))
# A layer instance is callable on a tensor, and returns a tensor.
x = layers.Dense(64, activation=’relu’)(inputs)
x = layers.Dense(64, activation=’relu’)(x)
predictions = layers.Dense(10, activation=’softmax’)(x)
# Instantiate the model given inputs and outputs.
model = tf.keras.Model(inputs=inputs, outputs=predictions)
此类模型也可使用以上同种简单命令进行编译和训练.
更多 Functional API 内容:https://www.tensorflow.org/guide/keras#functional_api
1.5. Model Subclassing API
可使用 Model Subclassing API 构建可完全自定义的模型. 在类方法主体中,可以采用此模式命令式地定义正向传递. 例如:
class MyModel(tf.keras.Model):
def __init__(self):
super(MyModel, self).__init__()
# Define your layers here.
self.dense_1 = layers.Dense(32, activation=’relu’)
self.dense_2 = layers.Dense(num_classes, activation=’sigmoid’)
def call(self, inputs):
# Define your forward pass here,
# using layers you previously defined in `__init__`
x = self.dense_1(inputs)
return self.dense_2(x)
此类模型更加灵活,但也更难调试.
这三类模型均可使用简单的编译与调整命令(如前文所示)进行编译和训练,也可自行编写自定义训练循环,以实现完全控制.
例如:
model = MyModel()
with tf.GradientTape() as tape:
logits = model(images, training=True)
loss_value = loss(logits, labels)
grads = tape.gradient(loss_value, model.variables)
optimizer.apply_gradients(zip(grads, model.variables))
更多 Model Subclassing 模式的相关示例:tensorflow.org/tutorials 中“研究与实验” 部分.
1.6. 如果以上三种模式均不适用,该怎么办?
如果发现 tf.keras 不适用于自身应用领域,我们还提供其他多种途径:
- 单独使用 Keras 模型定义中的 tf.keras.layers,然后自行编写梯度和训练代码. 还可单独或独立使用 tf.keras.optimizers、tf.keras.initializers、tf.keras.losses 或 tf.keras.metrics.
- 此外,也可完全忽略 tf.keras,并使用较低层级的 TensorFlow、Python 和 AutoGraph 获取期望结果.
注,tf.layers 中的非面向对象层将被弃用,且 tf.contrib.*(包括 tf.contrib.slim 和 tf.contrib.learn 等高级 API)将无法在 TensorFlow 2.0 中使用.
1.7. Estimator 有何变化?
Estimator 在 Google 内部以及更广泛的 TensorFlow 社区中应用甚广. 我们已将数种模型打包为预创建的 Estimator,包括线性分类器、DNN 分类器、DNN 线性组合分类器(亦即广度与深度模型)和梯度提升树. 这些模型已投入生产并得到广泛部署;基于此,TensorFlow 2.0 中将会添加 Estimator API(包括预创建的 Estimator).
对于使用预创建 Estimator 的用户而言,新版中重点开发的 Keras 和 Eager Execution 对其产生的影响微乎其微. 我们可以更改预创建 Estimator 的实现方式,但会保持 API 界面不变. 我们还将继续添加作为预创建 Estimator 实现的模型的 Keras 版本,同时还会扩展 Keras,以更好地满足大规模生产需求.
换言之,在开发自定义架构,建议使用 tf.keras 而非 Estimator 来构建模型. 如果您在构建需要借助 Estimator 的基础架构,则可通过 model_to_estimator() 来转换模型,而我们会努力确保 Keras 在整个 TensorFlow 生态系统中顺利运行.
2. 简单的模型构建
Keras API 将成为 TensorFlow 中构建和训练模型的核心高级 API.
Keras API 使得使用 TensorFlow 开启项目变得简单. 重要的是,Keras 提供了几个模型构建 API ( Sequential, Functional, 和 Subclassing ),因此可以选择适合的抽象级别. TensorFlow 的实现包含多项增强功能,包括即时迭代和直观调试,以及 tf.data,用于构建可扩展的输入管道.
下面是一个工作流程示例 ( 在接下来的几个月里,我们将更新下面所述内容的指南 ):
[1] - 使用 tf.data 加载数据. 使用输入管道读取训练数据,用 tf.data 创建的输入线程读取训练数据. 使用 tf.feature_column 描述特征,例如嵌套和特征交叉. 还支持从内存数据(例如 NumPy)中方便地输入
[2] - 使用 tf. Keras 或 Premade Estimators 构建、训练和验证模型. Keras 与 TensorFlow 的其余部分紧密集成,因此可以随时访问 TensorFlow 的功能. 一组标准的打包模型 ( 例如,线性或逻辑回归、梯度增强树、随机森林 ) 也可以直接使用 ( 利用 tf.estimator API 实现 ). 如果不想从头开始训练一个模型,很快就能通过 TensorFlow Hub 的模块利用迁移学习来训练 Keras 或 Estimator 模型
[3] - 使用 eager execution 运行和调试,然后在图形上使用 tf.function. TensorFlow 2.0 在默认情况下以 eager execution 方式运行,以便于使用和顺利调试. 此外,tf.function annotation 透明地将 Python 程序转换成 TensorFlow 图. 这个过程保留了 1.x TensorFlow 基于图执行的所有优点:性能优化、远程执行以及轻松序列化、导出和部署的能力,同时增加了使用简单的 Python 表达程序的灵活性和易用性
[4] - 使用分布策略进行分布式训练. 对于大型机器学习训练任务来讲,Distribution Strategy API 使得在不更改模型定义的情况下,在不同硬件配置上分布和训练模型变得很容易. 由于 TensorFlow 提供了对 CPU、GPU 和 TPU 等一系列硬件加速器的支持,因此可以将训练工作负载分布到单节点 / 多加速器以及多节点 / 多加速器配置,包括 TPU Pods. 虽然此 API 支持各种集群配置,但还提供了在本地或云环境中部署 Kubernetes 集群训练的模板
[5] - 导出到 SavedModel. TensorFlow 将在 SavedModel 上标准化,作为 TensorFlowServing、TensorFlow Lite、TensorFlow.js、TensorFlow Hub 等的交换格式
3. 在任何平台上的生产环境中进行稳健的模型部署
TensorFlow 始终为生产提供了直接途径. 无论是在服务器、边缘设备或者 web上,无论您使用哪种语言或平台,TensorFlow 都可以轻松地训练和部署模型. 在 TensorFlow 2.0 中,我们通过标准化交换格式和调整 API 来提高平台和组件之间的兼容性和一致性.
一旦训练并保存了模型,就可以直接在应用程序中执行它,或者使用以下部署库之一为它提供服务:
- TensorFlow Serving:TensorFlow 库允许模型通过 HTTP / REST 或 gRPC / 协议缓冲区提供服务
- TensorFlow Lite:TensorFlow 针对移动和嵌入式设备的轻量级解决方案提供了在 Android、iOS 和 Raspberry Pi 和 Edge tpu 等嵌入式系统上部署模型的能力
- TensorFlow.js:支持在 JavaScript 环境中部署模型,例如通过 Node.js 在 web 浏览器或服务器端部署模型. TensorFlow.js 还支持用 JavaScript 定义模型,并使用类似于 keras 的 API 直接在 web 浏览器中进行训练
TensorFlow 还支持其他语言 ( 一些由更广泛的社区维护 ),包括 C, Java, Go, C#, Rust, Julia, R 等.
4. 为研究提供强大的实验工具
TensorFlow 使从概念到代码、从模型到发布的新思想变得容易. TensorFlow 2.0 集成了许多功能,可以在不牺牲速度或性能的情况下定义和训练最新模型:
- Keras Functional API 和 Model Subclassing API:允许创建复杂的拓扑,包括使用剩余层、自定义的多输入 / 输出模型和强制写入的正向传递
- 自定义训练逻辑:使用 tf.GradientTape 和 tf.custom_gradient 对梯度计算进行细粒度控制
- 为了获得更大的灵活性和更好的控制,低级别 TensorFlow API 始终可用,并与高级别抽象结合在一起,以实现完全可定制的逻辑
TensorFlow 2.0 带来了一些新功能,允许研究人员和高级用户使用丰富的扩展 ( 如 Ragged Tensors, TensorFlow Probability, Tensor2Tensor 等) 进行实验.
除了这些功能外,TensorFlow 提供 eager excution,便于原型制作和调试,Distribution Strategy API 和 AutoGraph进行规模化训练, 以及对 TPU 的支持, 使 TensorFlow 2.0 成为一个易于使用、可定制和高度可扩展的平台,用于进行最先进的机器学习研究并将研究转化为生产流水线.
5. TensorFlow 1.x 和 2.0 的区别
自从我们最初开源 TensorFlow 以来,已经有了许多版本和 API 迭代. 随着机器学习的快速发展,该平台得到了极大的发展,现在支持具有不同需求的不同用户组合. 使用 TensorFlow 2.0,我们有机会清理和模块化基于语义版本控制的平台.
以下是一些较大的变化:
- 删除 queue runner 以支持 tf.data
- 删除图形集合
- 改变变量的处理方式
- 符号的移动和重命名
此外,tf_contrib 将从 TensorFlow 核心存储库和构建流程中删除. TensorFlow 的 contrib 模块已经超出了单个存储库所能维护和支持的范围. 较大的项目最好单独维护,而较小的扩展将逐步过渡到核心 TensorFlow 代码. 一个特别兴趣小组 ( SIG ) 已经成立,以维持和进一步发展未来一些更重要的 contrib 项目.
6. 兼容性和连续性
为了简化向 TensorFlow 2.0 的过渡,将有一个转换工具,它可以更新 TensorFlow 1.x Python 代码以使用 TensorFlow 2.0 兼容 API,或者标记代码无法自动转换的情况.
并非所有更改都可以完全自动完成. 例如,某些已弃用的 API 没有直接等效项. 这就是我们引入 tensorflow.compat.v1 兼容性模块的原因,该模块保留了对完整 TensorFlow 1.x API(不包括 tf.contrib)的支持. 该模块将在 TensorFlow 2.x 的生命周期内维护,并允许使用 TensorFlow 1.x 编写的代码保持功能.
此外,SavedModels 或存储的 GraphDefs 将向后兼容. 使用 1.x 保存的 SavedModels 将继续在 2.x 中加载和执行. 但是,2.0 中的更改将意味着原始检查点中的变量名称可能会更改,因此使用 2.0 之前的检查点而具有已转换为 2.0 的代码时可能无法保证正常工作.
详细信息,请参阅 TensorFlow 2.0 指南:
https://github.com/tensorflow/docs/blob/master/site/en/r2/guide/effective_tf2.md
我们相信 TensorFlow 2.0 将为应用开发带来巨大的益处,我们已投入大量精力使转换变得尽可能简单. 但是,我们也认识到迁过渡当前的线程需要时间,我们非常关心社区目前对学习和使用 TensorFlow 的投资. 我们将在最后的 1.x 版本中提供 12 个月的安全补丁,以便为现有用户提供充足的时间进行过渡并获得 TensorFlow 2.0 的所有优势.
7. TensorFlow 2.0 的时间表
TensorFlow 2.0 预览版将于今年年初发布.
何必要等? 已经可以通过使用 tf.keras 和 eager execution,预打包模型和部署库来开发 TensorFlow 2.0 了. Distribution Strategy API 目前已部分可用.
我们对 TensorFlow 2.0 以及即将到来的变化感到非常兴奋. TensorFlow 已经从一个用于深度学习的软件库成长为一个适用于所有机器学习类型的完整生态系统. TensorFlow 2.0 将简单易用,适用于所有平台上的所有用户.