本笔记参照TensorFlow Guide官方教程,主要是对‘Effictive TensorFlow 2’教程内容翻译和内容结构编排,原文链接:Effictive TensorFlow 2


高效的TF 2

  • 一、主要改动概览
    • 1.1 API 清理(cleanup)
    • 1.2 即刻执行(Eager execution)
    • 1.3 没有全局变量(No more globals)
    • 1.4 功能,而不是会话(Functions,not sessions)
  • 二、使用TensorFlow 2.0 的建议(Recommendations for idiomatic TensorFlow2.0)
    • 2.1 将代码重构为更小的函数(Refactor your code into smaller functions)
    • 2.2 使用Keras层和模型来管理变量(Use Keras layers and models to manage variables)
    • 2.3 将‘tf.data.Datasets’和‘@tf.function’结合(Combine tf.data.Datasets and @tf.function)
    • 2.4 利用Python控制流签名(Take advantage of AutoGraph with Python control flow)
    • 2.5 用‘tf.metrics’聚合数据,‘tf.summary’记录数据(tf.metrics aggregates data and tf.summary logs them)
    • 2.6 使用‘tf.config.experimental_run_functions_eagerly()’调试(Use tf.config.experimental_run_functions_eagerly() when debugging)

TensorFlow2.0 移除了冗余的API,也让API一致性更强了(统一的RNNs,统一的优化器),并且在即刻执行里集成了Python运行环境。

许多RFC已经解释了对Tensorflow 2.0de 变化。本指南展示了TensorFlow 2.0开发应该是什么样的并假设我们对TensorFlow 1.x 有一定的了解。

一、主要改动概览

1.1 API 清理(cleanup)

在TF2.0里许多API都移除了,其中几个大改动是移除了‘tf.app’,‘tf.flags’,‘tf.logging’来支持现在开源的absl-py,转移了保存在‘tf.contrib’中的项目,通过将更少用到的功能移动到子包(像tf.math)形式清理了主要‘tf.*’命名空间。一些API 已经在2.0里被等价替换了(tf.summary\tf.keras.metrics\tf.keras.optimizers)。自动应用这些重命名的最简单的方法是使用V2升级脚本(v2 upgrade script)

1.2 即刻执行(Eager execution)

TensorFlow1.X要求用户通过生成‘tf.*’API 调用来手动地将抽象语法树(图)缝合在一起。然后,它需要用户通过向session.run()调用中传递一组输出张量和输入张量来手动编译抽象语法树。 TensorFlow 2.0里的即刻执行就像Python编译器那样,在2.0,图(graph)和会话(session)感觉像是实现细节。

即刻执行的一个显著副产品是不再需要‘tf.control_dependencies()’,因为所有代码行都是按顺序执行的。(在tf.function里,带有副作用的代码是按编写时的顺序执行的)

1.3 没有全局变量(No more globals)

TensorFlow 1.X严重依赖显式地全局命名空间。当我们调用‘tf.Variable()’,它会被放进默认的图(graph)中,并且始终在那儿,即使我们丢失了指向它的Python变量轨迹。我们可以恢复‘tf.Variable’,但只有我们知道它被创建时使用的名字才行,如果我们没有控制变量的创建,这样就很困难。因此,各种各样的扩散机制再次试图帮助用户找到他们的变量,以及一些用来寻找用户创建变量的框架:变量作用域,全局集,辅助方法,像:‘tf.get_global_step()’,‘tf.global_variables_initializer()’,通过所有可训练变量静默计算梯度的优化器(optimizer)等等。TensorFlow 2.0为了支持默认机制,消除了上述所有机制。默认机制可以保持对变量的跟踪。如果我们丢了变量的轨迹,它会被垃圾桶收集

跟踪变量的需求给用户创建了一些额外的工作,但是使用Keras对(参见下面的内容),这种负担就会被最小化。

1.4 功能,而不是会话(Functions,not sessions)

‘session.run()’调用几乎与函数调用一样:指定要调用的输入和函数,然后返回一组输出。在TensorFlow 2.0中,可以使用tf.function()修饰一个Python函数,将其标记为JIT编译,以便TensorFlow将其作为一个图运行(函数2.0RFC)。这个机制允许TensorFlow 2.0获得图模式的所有好处:
- 性能:功能可以优化(节点剪枝node pruning、核融合等)。
- 可移植性:功能可以被导出/重导入(‘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的表达方式。但由于TensofFlow具有可移植性,在没有Python解释器的上下文中如mobile、C++、JavaScript,也可以执行。可以帮助用户避免在添加‘@tf.function’时重写代码。AutoGraph将Python结构的一个子集转换成他们的TensorFlow等价物:
- for/while->‘tf.while_loop’(break和continue都支持)
- if->‘tf.cond’
- ‘for _ in dataset’->‘dataset.reduce’
AutoGraph系列支持任意的控制流网络,这使得高效和简洁的实现许多复杂的ML程序成为可能,例如序列模型,强化学习,自定义训练循环等等。

二、使用TensorFlow 2.0 的建议(Recommendations for idiomatic TensorFlow2.0)

2.1 将代码重构为更小的函数(Refactor your code into smaller functions)

TensoFlow 1.X中常见的使用模式是‘kitchen sink’策略,所有可能的计算的并集被预先安排好,然后通过session.run()对选择的张量进行评估。在TensorFlow2.0中,用户应该根据需要将代码重构为更小的函数。通常,没有必要用tf.function来修饰这些小函数;只用tf.function来修饰高级计算–例如,一个训练步骤或模型的前向传递。

2.2 使用Keras层和模型来管理变量(Use Keras layers and models to manage variables)

Keras模型和层提供了非常方便的‘variables’和‘trainable_variables’属性,他们递归地收集所有的因变量,这使得在本地管理变量到使用它们的地方变得很容易。
对比:

def dense(x, W, b):return tf.nn.sigmoid(tf.matmul(x, W) + b)@tf.function
def multilayer_perceptron(x, w0, b0, w1, b1, w2, b2 ...):x = dense(x, w0, b0)x = dense(x, w1, b1)x = dense(x, w2, b2)...# You still have to manage w_i and b_i, and their shapes are defined far away from the code.

使用Keras的版本:

# Each layer can be called, with a signature equivalent to linear(x)
layers = [tf.keras.layers.Dense(hidden_size, activation=tf.nn.sigmoid) for _ in range(n)]
perceptron = tf.keras.Sequential(layers)# layers[3].trainable_variables => returns [w3, b3]
# perceptron.trainable_variables => returns [w0, b0, ...]

Keras层和模型继承自tf.train.Checkpointable,并且集成有@tf.function,它使直接设置检查点或从Keras对象导出SavedModels成为可能,这样我们不必使用Keras的‘fit()’API来利用这些集成。

下面是一个转移学习示例,演示Keras如何简化收集相关变量子集的工作。假设我们正在训练一个具有共享主干的多头模型:

trunk = tf.keras.Sequential([...])
head1 = tf.keras.Sequential([...])
head2 = tf.keras.Sequential([...])path1 = tf.keras.Sequential([trunk, head1])
path2 = tf.keras.Sequential([trunk, head2])# Train on primary dataset
for x, y in main_dataset:with tf.GradientTape() as tape:prediction = path1(x)loss = loss_fn_head1(prediction, y)# Simultaneously optimize trunk and head1 weights.gradients = tape.gradient(loss, path1.trainable_variables)optimizer.apply_gradients(zip(gradients, path1.trainable_variables))# Fine-tune second head, reusing the trunk
for x, y in small_dataset:with tf.GradientTape() as tape:prediction = path2(x)loss = loss_fn_head2(prediction, y)# Only optimize head2 weights, not trunk weightsgradients = tape.gradient(loss, head2.trainable_variables)optimizer.apply_gradients(zip(gradients, head2.trainable_variables))# You can publish just the trunk computation for other people to reuse.
tf.saved_model.save(trunk, output_path)

2.3 将‘tf.data.Datasets’和‘@tf.function’结合(Combine tf.data.Datasets and @tf.function)

当迭代适合内存的训练数据时,可以随意使用常规的Python迭代。否则‘tf.data.Dataset’是从磁盘传输训练数据的最佳方式。数据集是可迭代对象(iterables)(而不是迭代器),在即刻执行模式其工作方式与其他Python迭代器一样。通过将代码包装在‘tf.function()’中,我们可以充分利用dataset异步预抓取/流式(prefetching/streaming)特性,该方法用使用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.gradient(loss, model.trainable_variables)optimizer.apply_gradients(zip(gradients, model.trainable_variables))

如果我们使用Keras‘.fit()’ API,就不必担心数据集迭代:

model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)

2.4 利用Python控制流签名(Take advantage of AutoGraph with Python control flow)

AutoGraph可以将数据依存控制流(data-dependent control flow)转换成图模式等价物(graph-mode equivalents),像‘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_celldef 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

2.5 用‘tf.metrics’聚合数据,‘tf.summary’记录数据(tf.metrics aggregates data and tf.summary logs them)

如果要记录总结,在TensorFlow 2.0 可以使用‘tf.summary.(scalar|histogram|…)’,并且使用上下文管理器(context manager)将总结重新直传给编写人员。(如果忽略了上下文管理器,什么也不会发生),不像TF 1.X,总结直接发送给编写人员,没有单独的‘merge’操作,也没有单独的‘add_summary()’调用,这意味着必须在callsite中提供步骤值。

summary_writer = tf.summary.create_file_writer('/tmp/summaries')
with summary_writer.as_default():tf.summary.scalar('loss', 0.1, step=42)

为了在数据记录为摘要前聚合它们,我们可以使用‘tf.metrics’。指标是有状态的:它们累加值并在调用‘.result()’时返回累积结果。使用‘.reset-states()’清楚累积值。

def train(model, optimizer, dataset, log_freq=10):avg_loss = tf.keras.metrics.Mean(name='loss', dtype=tf.float32)for images, labels in dataset:loss = train_step(model, optimizer, images, labels)avg_loss.update_state(loss)if tf.equal(optimizer.iterations % log_freq, 0):tf.summary.scalar('loss', avg_loss.result(), step=optimizer.iterations)avg_loss.reset_states()def test(model, test_x, test_y, step_num):loss = loss_fn(model(test_x), test_y)tf.summary.scalar('loss', loss, step=step_num)train_summary_writer = tf.summary.create_file_writer('/tmp/summaries/train')
test_summary_writer = tf.summary.create_file_writer('/tmp/summaries/test')with train_summary_writer.as_default():train(model, optimizer, dataset)with test_summary_writer.as_default():test(model, test_x, test_y, optimizer.iterations)

通过将TensorBoard指向摘要日志目录,可视化生成的摘要:

tensorboard --logdir /tmp/summaries

2.6 使用‘tf.config.experimental_run_functions_eagerly()’调试(Use tf.config.experimental_run_functions_eagerly() when debugging)

在TensorFlow 2.0中,即刻执行让我们可以逐步运行代码来检查形状(shape)、数据类型和值。某些API,比如tf.function,tf.keras等被设计成使用图执行来提高性能和可移植性。在调试时,使用‘tf.config.experimental_run_functions_eagerly(True)’在这段代码中使用立即执行。
例如:

@tf.function
def f(x):if x > 0:import pdbpdb.set_trace()x = x + 1return xtf.config.experimental_run_functions_eagerly(True)
f(tf.constant(1))


Keras模型和其它API也支持即刻执行:

class CustomModel(tf.keras.models.Model):@tf.functiondef call(self, input_data):if tf.reduce_mean(input_data) > 0:return input_dataelse:import pdbpdb.set_trace()return input_data // 2tf.config.experimental_run_functions_eagerly(True)
model = CustomModel()
model(tf.constant([-2, -4]))

TensorFlow2.0 Guide官方教程 学习笔记20 -‘Effective TensorFlow 2‘相关推荐

  1. TensorFlow2.0 Guide官方教程 学习笔记17 -‘Using the SavedModel format‘

    本笔记参照TensorFlow官方教程,主要是对'Save a model-Training checkpoints'教程内容翻译和内容结构编排,原文链接:Using the SavedModel f ...

  2. TensorFlow2.0 Guide官方教程 学习笔记10- Eager execution

    本笔记参照TensorFlow官方教程,主要是对'Eager execution'教程内容翻译和内容结构编排,原文链接:Eager execution 目录 一.创建环境和基本使用 二.动态控制流 三 ...

  3. 【从零开始的大数据学习】Flink官方教程学习笔记(一)

    Flink官方教程学习笔记 学习资源 基础Scala语法 Scala数据结构专题 声明变量 代码块 函数(function) 方法(methods) Traits (接口) class(类) tupl ...

  4. Dynamic Quantization PyTorch官方教程学习笔记

    诸神缄默不语-个人CSDN博文目录 本文是PyTorch的教程Dynamic Quantization - PyTorch Tutorials 1.11.0+cu102 documentation的学 ...

  5. 【网络教程】Iptables官方教程-学习笔记5--IPTABLES MATCH

    这篇博客介绍iptables和netfilter中所有可用的匹配,章节比较厂,没必要去学习每个匹配的具体细节,大致了解下即可,后续要用到再深入掌握它. 一 .Iptables 的匹配(match) 在 ...

  6. 【网络教程】IPtables官方教程--学习笔记3

    一.遍历表和链 本节我们将讨论信息包如何遍历不同的链(chains)以及以什么样的顺序.我们也会讨论表(tables)的遍历顺序,以及研究与内核相关的某些其它组件所涉及的问题,也就是说不同的路由决策等 ...

  7. Ceres Solver 官方教程学习笔记(十二)——非线性最小二乘法建模Modeling Non-linear Least Squares (下)

    这一部分主要是最后的Problem比较重要. 带条件的代价函数ConditionedCostFunction 这个类使用户可以在使用封装好的代价函数的同时,对残差值加入一定的条件限制.举个例子,现在已 ...

  8. Opencv4 -Python官方教程学习笔记33---BRIEF

    理论 我们知道SIFT使用128维矢量作为描述符.由于它使用浮点数,因此基本上需要512个字节.同样,SURF最少也需要256个字节(用于64像素).为数千个功能部件创建这样的向量会占用大量内存,这对 ...

  9. PCL学习笔记(二):PCL官方教程学习

    PCL学习笔记(二):PCL官方教程学习 PCD文件制作 Features 表面法线提取 Keypoints 提取NARF关键点 KdTree Range Image How to create a ...

最新文章

  1. poj1466(二分图最大独立集)
  2. fatfree-f3小型php框架(二)
  3. Debug无忧!清华校友打造Python调试神器:反向追踪变量、数据流等 | 开源
  4. kettle 脚本 java_Kettle 执行SQL脚本
  5. CentOS7下安装Redis — 单节点
  6. linux生产上线工具,Linux 产能工具及其使用技巧
  7. Linux Shell脚本入门教程系列之(九)Shell判断 if else 用法
  8. java线程的小问题与回答
  9. Egret入门学习日记 --- 第十七篇(书中 7.4~8.2节 内容)
  10. 计算机word怎么写,电脑word怎么用?
  11. webpack配置文件的抽离
  12. 基于协同过滤算法的商品推荐购物电商系统
  13. 递增序列-2019年蓝桥杯国赛填空题题目答案及分析
  14. 五十个SQL基本语句,来看看你的SQL语言过关了吗?
  15. 数值分析 解线性方程组的直接法(一)
  16. 基于JAVA东理咨询交流论坛计算机毕业设计源码+系统+数据库+lw文档+部署
  17. 深入理解 TORCH.NN
  18. 【高德地图进阶】--- 添加城市版块纹理
  19. 恒大kk服务器信息端口,恒大kk手机客户端服务器
  20. 【音特电子】整流二极管的工作原理与选型

热门文章

  1. 004coursera网站中的VTT字幕的使用
  2. Q2财报后股价遭重挫,搜狗的AI招牌也失灵?从翻译录音笔体验看背后的花拳绣腿...
  3. 您有一份OFFER请查收!
  4. ATEN CS22DP 2端口USB DisplayPort带线式KVM多电脑切换器 (外接式切换按键)
  5. 傲慢与偏见之 - 因果倒置的锦上添花
  6. 科目三道路驾驶技能考试使用计算机系统,科目三道路驾驶技能考试方法是怎样的?...
  7. WPS文字在线转换成Word
  8. Paddle入门实战系列(二)基于PaddleOCR的体检报告识别
  9. 快速入门Opentracing-cpp
  10. 已知华氏温度f c语言,编程题:已知两种温度的换算公式C=(5/9)(F-32),试编写一个程序输入华氏度F,输出摄氏度。...