TensorFlow层次结构中的三种计算图

三种计算图

所谓计算图,计算图由节点(nodes)和线(edges)组成。节点表示操作符 Operator,或者称之为算子,线表示计算间的依赖。实线表示有数据传递依赖,传递的数据即张量。虚线通常可以表示控制依赖,即执行先后顺序。

有三种计算图的构建方式:静态计算图,动态计算图,以及 Autograph。在 TensorFlow1.0 时代,采用的是静态计算图,需要先使用 TensorFlow 的各种算子创建计算图,然后再开启一个会话 Session,显式执行计算图。

而在 TensorFlow2.0 时代,采用的是动态计算图,即每使用一个算子后,该算子会被动态加入到隐含的默认计算图中立即执行得到结果,而无需开启 Session。而在 TensorFlow2.0 时代,采用的是动态计算图,即每使用一个算子后,该算子会被动态加入到隐含的默认计算图中立即执行得到结果,而无需开启 Session。

使用动态计算图即 Eager Excution 的好处是方便调试程序,它会让 TensorFlow 代码的表现和 Python 原生代码的表现一样,写起来就像写 numpy 一样,各种日志打印,控制流全部都是可以使用的。使用动态计算图的缺点是运行效率相对会低一些。因为使用动态图会有许多次 Python 进程和 TensorFlow 的 C++进程之间的通信。而静态计算图构建完成之后几乎全部在 TensorFlow 内核上使用 C++ 代码执行,效率更高。此外静态图会对计算步骤进行一定的优化,剪去和结果无关的计算步骤。

如果需要在 TensorFlow2.0 中使用静态图,可以使用@tf.function 装饰器将普通 Python 函数转换成对应的 TensorFlow 计算图构建代码。运行该函数就相当于在 TensorFlow1.0 中用 Session 执行代码。使用 tf.function 构建静态图的方式叫做 Autograph.

静态计算图

在 TensorFlow 1.0 中,使用静态计算图分两步,第一步定义计算图,第二步在会话中执行计算图。


   
import tensorflow as tf

#定义计算图
g = tf.Graph()
with g.as_default():
    #placeholder为占位符,执行会话时候指定填充对象
    x = tf.placeholder(name='x', shape=[], dtype=tf.string)
    y = tf.placeholder(name='y', shape=[], dtype=tf.string)
    z = tf.string_join([x,y],name = 'join',separator=' ')

#执行计算图
with tf.Session(graph = g) as sess:
    print(sess.run(fetches = z,feed_dict = {x:"hello",y:"world"}))

TensorFlow2.0 为了确保对老版本 tensorflow 项目的兼容性,在 tf.compat.v1 子模块中保留了对 TensorFlow1.0 那种静态计算图构建风格的支持。

import tensorflow as tf

g = tf.compat.v1.Graph()
with g.as_default():
    x = tf.compat.v1.placeholder(name='x', shape=[], dtype=tf.string)
    y = tf.compat.v1.placeholder(name='y', shape=[], dtype=tf.string)
    z = tf.strings.join([x,y],name = "join",separator = " ")

with tf.compat.v1.Session(graph = g) as sess:
    # fetches的结果非常像一个函数的返回值,而feed_dict中的占位符相当于函数的参数序列。
    result = sess.run(fetches = z,feed_dict = {x:"hello",y:"world"})
    print(result)

   

动态计算图

在 TensorFlow 2.0 中,使用的是动态计算图和 Autograph。在 TensorFlow1.0 中,使用静态计算图分两步,第一步定义计算图,第二步在会话中执行计算图。

动态计算图已经不区分计算图的定义和执行了,而是定义后立即执行。因此称之为 Eager Excution.

# 动态计算图在每个算子处都进行构建,构建后立即执行

x = tf.constant("hello")
y = tf.constant("world")
z = tf.strings.join([x,y],separator=" ")

tf.print(z)

# 可以将动态计算图代码的输入和输出关系封装成函数

def strjoin(x,y):
    z =  tf.strings.join([x,y],separator = " ")
    tf.print(z)
    return z

result = strjoin(tf.constant("hello"),tf.constant("world"))
print(result)

签名

动态计算图运行效率相对较低。可以用 @tf.function 装饰器将普通 Python 函数转换成和 TensorFlow1.0 对应的静态计算图构建代码。在 TensorFlow1.0 中,使用计算图分两步,第一步定义计算图,第二步在会话中执行计算图。在 TensorFlow2.0 中,如果采用 Autograph 的方式使用计算图,第一步定义计算图变成了定义函数,第二步执行计算图变成了调用函数。

实践中,我们一般会先用动态计算图调试代码,然后在需要提高性能的地方利用 @tf.function 切换成 Autograph 获得更高的效率。

import tensorflow as tf

# 使用autograph构建静态图
@tf.function
def strjoin(x,y):
    z =  tf.strings.join([x,y],separator = " ")
    tf.print(z)
    return z

result = strjoin(tf.constant("hello"),tf.constant("world"))

print(result)

import datetime

# 创建日志
import os
stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
logdir = os.path.join('data', 'autograph', stamp)

## 在 Python3 下建议使用 pathlib 修正各操作系统的路径
# from pathlib import Path
# stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
# logdir = str(Path('./data/autograph/' + stamp))

writer = tf.summary.create_file_writer(logdir)

# 开启autograph跟踪
tf.summary.trace_on(graph=True, profiler=True)

# 执行autograph
result = strjoin("hello","world")

# 将计算图信息写入日志
with writer.as_default():
    tf.summary.trace_export(
        name="autograph",
        step=0,
        profiler_outdir=logdir)

然后我们可以启动 TensorBoard 查看 AutoGraph:

# 启动 tensorboard在jupyter中的魔法命令
%load_ext tensorboard

# 启动tensorboard
%tensorboard --logdir ./data/autograph/

  

相关推荐

  1. 存储器层次结构

    2023-12-26 16:56:03       30 阅读
  2. 计算服务模式

    2023-12-26 16:56:03       27 阅读
  3. QT程序执行时间精准计算方法及对比

    2023-12-26 16:56:03       45 阅读
  4. 数据库服务器数据结构

    2023-12-26 16:56:03       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-26 16:56:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-26 16:56:03       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-26 16:56:03       82 阅读
  4. Python语言-面向对象

    2023-12-26 16:56:03       91 阅读

热门阅读

  1. 【ARM 嵌入式 编译系列 10.4 -- 生成二进制文件】

    2023-12-26 16:56:03       58 阅读
  2. 视觉SLAM十四讲|【二】李群与李代数

    2023-12-26 16:56:03       49 阅读
  3. Git 的基本概念和使用方式

    2023-12-26 16:56:03       58 阅读
  4. docker-compose 安装gitlab

    2023-12-26 16:56:03       63 阅读
  5. Verilog 14: 阻塞和非阻塞赋值的异同

    2023-12-26 16:56:03       43 阅读
  6. 【Netty】案例-群聊天室实现

    2023-12-26 16:56:03       48 阅读
  7. LINUX自启动线程学习笔记

    2023-12-26 16:56:03       59 阅读