linux工程师,RHCE
分类: 架构设计与优化
2019-02-18 18:21:58
为提高 TensorFlow 的工作效率,TensorFlow 2.0 进行了多项更改,包括删除了多余的
API,使API 更加一致统一,例如统一的 RNNs (循环神经网络),统一的优化器,并且Python 运行时更好地集成了 Eager
为提高 TensorFlow 的工作效率,TensorFlow 2.0 进行了多项更改,包括删除了多余的 API,使API
更加一致统一,例如统一的 RNNs (循环神经网络),统一的优化器,并且Python 运行时更好地集成了 Eager execution 。
许多 RFC 已经对 TensorFlow 2.0 的这些更改给出了解释。本指南基于您对 TensorFlow 1.x 有一定的了解的前提,为您介绍在 TensorFlow 2.0 中的开发有什么不同。
API 整理
在 TensorFlow 2.0 中,有许多 1.X 的 API 被删除或移动 了。也有部分 1.X 的 API 被 2.0 版本的等价
API 所替代:tf.summary,tf.keras.metrics 和
tf.keras.optimizers。自动应用这些重命名,最简单的方法是使用 TensorFlow 2.0 升级脚本。
Eager execution
TensorFlow 1.X 要求用户通过调用 tf.* API
手动的将抽象语法树(图)拼接在一起。然后,它要求用户将一组输出张量和输入张量传递给 session.run()
调用,来手动编译抽象语法树。相比之下,TensorFlow 2.0 executes eagerly(如正常使用 Python 一样)在 2.0
的版本中,其 graphs(抽象语法树)和 sessions 在实现的细节上应该是一样的。
不再有全局变量
TensorFlow 1.X 非常依赖于隐式全局命名空间。当你调用 tf.Variable 时,它会被放入默认图中,即使你忘记了指向它的
Python 变量它也会留在那里。这时,您可以恢复该
tf.Variable(),但前提是您得知道它已创建的名称。如果您无法控制变量的创建,很难做到这一点。因此,各种机制以及寻找用户创建变量的框架不断涌现,试图帮助用户再次找到他们的变量。
TensorFlow 2.0 取消了所有这些机制(Variables 2.0 RFC),支持默认机制:跟踪变量! 如果你不再用到某个 tf.Variable,它就会被回收。
Functions, not sessions
session.run() 的调用几乎类似于函数调用:指定输入和要调用的函数,然后返回一组输出。在 TensorFlow 2.0
中,您可以使用 tf.function() 来修饰 Python 函数以将其标记为 JIT( Just-In-Time )编译,以便
TensorFlow 将其作为单个图运行(Functions 2.0 RFC)。
这种机制使得 TensorFlow 2.0 拥有图模式的许多优点:
性能:该函数可以被优化,例如节点修剪,内核融合等
可移植性:该函数可以导出 / 重新导入(SavedModel 2.0 RFC),允许用户重用和将 TensorFlow 函数作为模块共享
# TensorFlow 1.X
outputs = session.run(f(placeholder), feed_dict={placeholder: input})# TensorFlow 2.0
outputs = f(input)
由于能够自由地穿插 Python 和 TensorFlow 代码,您能够充分利用 Python 的表现力。而且,可移植的
TensorFlow 在没有 Python 解释器的情况下也可执行。比如:mobile,C ++ 和 JS。避免用户在添加
@tf.function 时重写代码,AutoGraph 会将 Python 构造的一个子集转换成 TensorFlow 等价物。
TensorFlow 2.0 常用的建议
将代码重构为更小的函数
TensorFlow 1.X 中的常见使用模式是 “kitchen sink” 策略,即预先列出所有可能计算的并集,然后通过
session.run() 计算选定的张量。在 TensorFlow 2.0 中,用户应该根据需求将代码重构为更小的函数。通常情况下,没有必要用
tf.function 来修饰这些较小的函数;仅使用 tf.function 来修饰高级计算 —
例如,使用只有一个步骤的训练或使用模型的正向传递,将代码重构为更小的函数。
使用 Keras 层和模型来管理变量
Keras 模型和层提供了方便的变量和 trainable_variables 属性,以递归方式收集所有因变量。这使得本地化管理变量非常方便。
Keras 层 / 模型继承自 tf.train.Checkpointable 并与 @ tf.function 集成,这使得直接检查点或从 Keras 对象导出 SavedModel 成为可能。您不一定要使用 Keras 的 fit() API 来集成。
结合 tf.data.Datasets 和 @tf.function
在迭代适合内存的训练数据时,可以使用常规的 Python 循环。除此之外,tf.data.Dataset
则是从磁盘传输训练数据的最好方法。数据集是可迭代的(不是迭代器),工作方式与其他 Python 循环类似。如果您想使用 AutoGraph
的等效图操作替换 Python 循环,可以通过将代码包装在 tf.function() 中,充分利用数据集异步预取 / 流功能来实现。
@tf.function
def train(model, dataset, optimizer):
for x, y in dataset:
with tf.GradientTape() as tape:
prediction = model(x)
loss = loss_fn(prediction, y)
gradients = tape.gradients(loss, model.trainable_variables)
optimizer.apply_gradients(gradients, model.trainable_variables)
如果您使用 Keras.fit() API,则无需担心数据集迭代。
model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)
利用 AutoGraph 和 Python 控制流程
AutoGraph 提供了一种将依赖于数据的控制流转换为图模式等价的方法,如 tf.cond 和 tf.while_loop。
数据相关控制流常见出现于序列模型中。tf.keras.layers.RNN 包装了 RNN 单元,允许您静态或动态地展开循环神经网络。为了演示,您可以重新实现动态展开,如下所示:
class DynamicRNN(tf.keras.Model):
def __init__(self, rnn_cell):
super(DynamicRNN, self).__init__(self)
self.cell = rnn_cell
def call(self, input_data):
# [batch, time, features] -> [time, batch, features]
input_data = tf.transpose(input_data, [1, 0, 2])
outputs = tf.TensorArray(tf.float32, input_data.shape[0])
state = self.cell.zero_state(input_data.shape[1], dtype=tf.float32)
for i in tf.range(input_data.shape[0]):
output, state = self.cell(input_data[i], state)
outputs = outputs.write(i, output)
return tf.transpose(outputs.stack(), [1, 0, 2]), state
使用 tf.metrics 聚合数据,使用 tf.summary 记录数据
一套完整的 tf.summary 接口即将发布。您可以使用以下命令访问 tf.summary 的 2.0 版本:
from tensorflow.python.ops import summary_ops_v2