Effective TensorFlow 2.0最佳实践摘要

这篇文章是Effective TensorFlow 2.0的一个摘要,如果嫌原文太长又是英文的话,看看这个就好了,给大家画了个重点。

在最近的一篇文章中(https://medium.com/tensorflow/whats-coming-in-tensorflow-2-0-d3663832e9b8),我们提到TensorFlow 2.0已经重新设计,重点是开发人员的生产力、简单性和易用性。

要更仔细地查看更改了什么,并了解最佳实践,请查看新的Effective TensorFlow 2.0指南(在GitHub上发布)。本文简要介绍了其中的内容。如果你对这些主题感兴趣,请前往指南了解更多信息!

主要变化的简介

有许多TensorFlow 2.0让用户更有生产力的变化,包括去除冗余的api,使api更一致的(统一RNNs),统一优化器,通过Eager execution更好地与Python运行时集成。

许多指南展示了TensorFlow 2.0开发的远景,这里假设你对TensorFlow 1.x有一定的了解。

API清理

在TF 2.0中,许多api要么消失了,要么被迁移了,其中一些api已经被2.0版本的同类api—— tf.summary, tf.keras.metrics和 tf.keras.optimizers所取代。自动应用这些重命名的最简单方法是使用v2升级脚本。

即时执行

TensorFlow 1.X要求用户通过tf.* API手动地将抽象语法树(图)拼接在一起。然后,它要求用户手动编译抽象语法树,方法是将一组输出张量和输入张量传递给一个 session.run()调用。相比之下,TensorFlow 2.0执行起来就是即时的(就像Python通常做的那样),在2.0中,图形和会话应该感觉像实现细节。

不再有全局变量

TensorFlow 1.X严重依赖于隐式全局名称空间。当你调用 tf.Variable()时,它将被放入默认图中,并且它将保持在那里,即使你丢失了指向它的Python变量的踪迹。然后你就能恢复 tf.Variable,但前提是你知道创建它时使用的名称。如果不控制变量的创建,则很难做到这一点。结果,各种各样的机制不断涌现,试图帮助用户再次找到他们的变量。

TensorFlow 2.0消除了所有这些机制,支持默认机制:跟踪变量!如果你失去了对一个 tf.Variable的跟踪,它就会被垃圾收集。有关详细信息,请参见指南。

函数,而不是会话

run()调用类似于函数调用:指定要调用的输入和函数,然后返回一组输出。在TensorFlow 2.0中,你可以使用 tf.function()来修饰一个Python函数,将其标记为JIT编译,以便TensorFlow将其作为一个图运行。

这个机制允许TensorFlow 2.0获得图形模式的所有好处:

  • 性能:功能可优化(节点剪枝、内核融合等)
  • 可移植性:该函数可以导出/重新导入,允许用户重用和共享模块化的TensorFlow函数。

通过自由地穿插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对象导出保存模型成为可能。你不必使用 Keras’s.fit() API来利用这些集成。

有关详细信息,请参见指南。

结合 tf.data.Datasets 和@tf.function

当迭代适合内存的训练数据时,可以随意使用常规的Python迭代。否则, tf.data.Dataset是从磁盘中传输训练数据的最佳方式。数据集是iterables(而不是iterators),并像其他Python iterables一样在Eager模式下工作。通过将代码封装在 tf.function()中,你可以充分利用dataset async预抓取/流特性,该函数使用使用AutoGraph的等价图形操作替换Python迭代。

@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)
用Python控制流来发挥AutoGraph的作用

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

英文原文:https://medium.com/tensorflow/effective-tensorflow-2-0-best-practices-and-whats-changed-a0ca48767aff

发表评论

电子邮件地址不会被公开。 必填项已用*标注