有三种计算图的构建方式:静态计算图,动态计算图,以及Autograph。

TensorFlow 2.0主要使用的是动态计算图和Autograph。

动态计算图易于调试,编码效率较高,但执行效率偏低。

静态计算图执行效率很高,但较难调试。

而Autograph机制可以将动态图转换成静态计算图,兼收执行效率和编码效率之利。

当然Autograph机制能够转换的代码并不是没有任何约束的,有一些编码规范需要遵循,否则可能会转换失败或者不符合预期。

我们会介绍Autograph的编码规范和Autograph转换成静态图的原理。

并介绍使用tf.Module来更好地构建Autograph。

上篇我们介绍了Autograph的编码规范,本篇我们介绍Autograph的机制原理。

一,Autograph的机制原理

当我们使用@tf.function装饰一个函数的时候,后面到底发生了什么呢?

例如我们写下如下代码。

import tensorflow as tf
import numpy as np @tf.function(autograph=True)
def myadd(a,b):
for i in tf.range(3):
tf.print(i)
c = a+b
print("tracing")
return c

后面什么都没有发生。仅仅是在Python堆栈中记录了这样一个函数的签名。

当我们第一次调用这个被@tf.function装饰的函数时,后面到底发生了什么?

例如我们写下如下代码。

myadd(tf.constant("hello"),tf.constant("world"))
tracing
0
1
2
<tf.Tensor: shape=(), dtype=string, numpy=b'helloworld'>

发生了2件事情,

第一件事情是创建计算图。

即创建一个静态计算图,跟踪执行一遍函数体中的Python代码,确定各个变量的Tensor类型,并根据执行顺序将算子添加到计算图中。 在这个过程中,如果开启了autograph=True(默认开启),会将Python控制流转换成TensorFlow图内控制流。 主要是将if语句转换成 tf.cond算子表达,将while和for循环语句转换成tf.while_loop算子表达,并在必要的时候添加 tf.control_dependencies指定执行顺序依赖关系。

相当于在 tensorflow1.0执行了类似下面的语句:

g = tf.Graph()
with g.as_default():
a = tf.placeholder(shape=[],dtype=tf.string)
b = tf.placeholder(shape=[],dtype=tf.string)
cond = lambda i: i<tf.constant(3)
def body(i):
tf.print(i)
return(i+1)
loop = tf.while_loop(cond,body,loop_vars=[0])
loop
with tf.control_dependencies(loop):
c = tf.strings.join([a,b])
print("tracing")

第二件事情是执行计算图。

相当于在 tensorflow1.0中执行了下面的语句:

with tf.Session(graph=g) as sess:
sess.run(c,feed_dict={a:tf.constant("hello"),b:tf.constant("world")})

因此我们先看到的是第一个步骤的结果:即Python调用标准输出流打印"tracing"语句。

然后看到第二个步骤的结果:TensorFlow调用标准输出流打印1,2,3。

当我们再次用相同的输入参数类型调用这个被@tf.function装饰的函数时,后面到底发生了什么?

例如我们写下如下代码。

myadd(tf.constant("hello"),tf.constant("world"))
0
1
2
<tf.Tensor: shape=(), dtype=string, numpy=b'helloworld'>

只会发生一件事情,那就是上面步骤的第二步,执行计算图。

所以这一次我们没有看到打印"tracing"的结果。

当我们再次用不同的的输入参数类型调用这个被@tf.function装饰的函数时,后面到底发生了什么?

例如我们写下如下代码。

myadd(tf.constant(1),tf.constant(2))
tracing
0
1
2
<tf.Tensor: shape=(), dtype=int32, numpy=3>

由于输入参数的类型已经发生变化,已经创建的计算图不能够再次使用。

需要重新做2件事情:创建新的计算图、执行计算图。

所以我们又会先看到的是第一个步骤的结果:即Python调用标准输出流打印"tracing"语句。

然后再看到第二个步骤的结果:TensorFlow调用标准输出流打印1,2,3。

需要注意的是,如果调用被@tf.function装饰的函数时输入的参数不是Tensor类型,则每次都会重新创建计算图。

例如我们写下如下代码。两次都会重新创建计算图。因此,一般建议调用@tf.function时应传入Tensor类型。

myadd("hello","world")
myadd("good","morning")

tracing

0

1

2

tracing

0

1

2

二,重新理解Autograph的编码规范

了解了以上Autograph的机制原理,我们也就能够理解Autograph编码规范的3条建议了。

1,被@tf.function修饰的函数应尽量使用TensorFlow中的函数而不是Python中的其他函数。例如使用tf.print而不是print.

解释:Python中的函数仅仅会在跟踪执行函数以创建静态图的阶段使用,普通Python函数是无法嵌入到静态计算图中的,所以 在计算图构建好之后再次调用的时候,这些Python函数并没有被计算,而TensorFlow中的函数则可以嵌入到计算图中。使用普通的Python函数会导致 被@tf.function修饰前【eager执行】和被@tf.function修饰后【静态图执行】的输出不一致。

2,避免在@tf.function修饰的函数内部定义tf.Variable.

解释:如果函数内部定义了tf.Variable,那么在【eager执行】时,这种创建tf.Variable的行为在每次函数调用时候都会发生。但是在【静态图执行】时,这种创建tf.Variable的行为只会发生在第一步跟踪Python代码逻辑创建计算图时,这会导致被@tf.function修饰前【eager执行】和被@tf.function修饰后【静态图执行】的输出不一致。实际上,TensorFlow在这种情况下一般会报错。

3,被@tf.function修饰的函数不可修改该函数外部的Python列表或字典等数据结构变量。

解释:静态计算图是被编译成C++代码在TensorFlow内核中执行的。Python中的列表和字典等数据结构变量是无法嵌入到计算图中,它们仅仅能够在创建计算图时被读取,在执行计算图时是无法修改Python中的列表或字典这样的数据结构变量的。

参考:

开源电子书地址:https://lyhue1991.github.io/eat_tensorflow2_in_30_days/

GitHub 项目地址:https://github.com/lyhue1991/eat_tensorflow2_in_30_days

【tensorflow2.0】AutoGraph的机制原理的更多相关文章

  1. Spring5.0源码学习系列之浅谈懒加载机制原理

    前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文挑一个比较重要的知识点Bean的懒加载进行学习 1.什么是懒加载? 懒加载(Lazy-ini ...

  2. 推荐模型DeepCrossing: 原理介绍与TensorFlow2.0实现

    DeepCrossing是在AutoRec之后,微软完整的将深度学习应用在推荐系统的模型.其应用场景是搜索推荐广告中,解决了特征工程,稀疏向量稠密化,多层神经网路的优化拟合等问题.所使用的特征在论文中 ...

  3. 推荐模型NeuralCF:原理介绍与TensorFlow2.0实现

    1. 简介 NCF是协同过滤在神经网络上的实现--神经网络协同过滤.由新加坡国立大学与2017年提出. 我们知道,在协同过滤的基础上发展来的矩阵分解取得了巨大的成就,但是矩阵分解得到低维隐向量求内积是 ...

  4. 推荐模型AutoRec:原理介绍与TensorFlow2.0实现

    1. 简介 本篇文章先简单介绍论文思路,然后使用Tensoflow2.0.Keras API复现算法部分.包括: 自定义模型 自定义损失函数 自定义评价指标RMSE 就题目而言<AutoRec: ...

  5. Google工程师亲授 Tensorflow2.0-入门到进阶

    第1章 Tensorfow简介与环境搭建 本门课程的入门章节,简要介绍了tensorflow是什么,详细介绍了Tensorflow历史版本变迁以及tensorflow的架构和强大特性.并在Tensor ...

  6. OAuth的机制原理讲解及开发流程

    本想前段时间就把自己通过QQ OAuth1.0.OAuth2.0协议进行验证而实现QQ登录的心得及Demo实例分享给大家,可一直很忙,今天抽点时间说下OAuth1.0协议原理,及讲解下QQ对于Oaut ...

  7. ASP.NET运行机制原理

    ASP.NET运行机制原理 一.浏览器和服务器的交互原理 (一).浏览器和服务器交互的简单描述: 1.通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去另一台电脑上访问文件一样,只不过 ...

  8. ASP.NET运行机制原理 ---浏览器与IIS的交互过程 自己学习 网上查了下别人写的总结的很好 就转过来了 和自己写的还好里嘻嘻

    一.浏览器和服务器的交互原理 (一).浏览器和服务器交互的简单描述: 1.通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去访问一台电脑上访问文件一样,只不过浏览器的访问请求是由被访问 ...

  9. 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】

    原文:[Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析] [注意:]团队里总是有人反映卸载Xamarin,清理不完全.之前写过如何完全卸载清理剩余的文件.今天写了Windows下的批命令 ...

随机推荐

  1. springmvc 的@ResponseBody 如何使用JSONP?

    JSONP解释 在解释JSONP之前,我们需要了解下”同源策略“这个概念,这对理解跨域有帮助.基于安全的原因,浏览器是存在同源策略机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载额文 ...

  2. swoole websocket_server 聊天室--群聊

    centos7  php7.2 swoole4.3 nginx1.8 websocket_server 代码 <?php $server = new Swoole\WebSocket\Serve ...

  3. 高可用Keepalived+LVS搭建流程

    本流程搭建1个master,1个backup节点的Keepalived,使用lvs轮询2个节点的服务. 一.使用版本 CentOS 7.7 Keepalived 1.3.5 ipvsadm 1.27( ...

  4. 通过nodejs实现文件的上传

    通过nodejs实现文件的上传 主要内容 本文将用来讲述如何通过nodejs进行文件上传,将会涉及到以下知识点: 通过express模块进行服务器的搭建 通过multer模块将上传的文件保存到指定目录 ...

  5. 【图文+视频新手也友好】Java一维数组详细讲解(内含练习题答案+详解彩蛋喔~)

    目录 视频讲解: 一.数组的概述 二.一维数组的使用 三.Arrays工具类中的sort方法(sort方法用的多,我们具体讲一下) 四.数组中的常见异常 五.一维数组练习题 六.彩蛋(本期视频使用的P ...

  6. TypeScript Jest 调试

    本文简要介绍了如何在 Jest 单元测试中利用 Chrome Node DevTools 来辅助调试. 背景 代码是 TS 写的 所测功能无 UI 界面,出现Bug后不容易定位 用 console 式 ...

  7. Go语言转义字符

    \a 匹配响铃符 (相当于 \x07) 注意:正则表达式中不能使用 \b 匹配退格符,因为 \b 被用来匹配单词边界, 可以使用 \x08 表示退格符. \f 匹配换页符 (相当于 \x0C) \t ...

  8. MATLAB神经网络(5) 基于BP_Adaboost的强分类器设计——公司财务预警建模

    5.1 案例背景 5.1.1 BP_Adaboost模型 Adaboost算法的思想是合并多个“弱”分类器的输出以产生有效分类.其主要步骤为:首先给出弱学习算法和样本空间($X$,$Y$),从样本空间 ...

  9. (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)

    协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...

  10. 谈谈MySQL数据库索引

    在分析MySQL数据库索引之前,很多小伙伴对数据结构中的树理解不够深刻.因此我们由浅入深一步步探讨树的演进过程,再一步步引出MySQL数据库索引底层数据结构. 一.二叉树 二叉查找树也称为有序二叉查找 ...