• 【TensorFlow】TensorFlow中的三种计算图


    系列文章目录

    第二章 TensorFlow  深度学习入门之 TensorFlow的核心概念


    目录

    系列文章目录

    文章目录

    前言

    一、三种计算图之间的关系

    二 、静态计算图

    1 TensorFlow1.0 中的静态计算图

    2 TensorFlow2.0 中的静态计算图

    三、 动态计算图

    四、TensorFlow2.0的Autograph



    前言

    计算图由节点(nodes)和线(edges)组成。

    节点表示操作符Operator,或者称之为算子,线表示计算间的依赖。

    实线表示有数据传递依赖,传递的数据即张量。

    虚线通常可以表示控制依赖,即执行先后顺序。

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


    一、三种计算图之间的关系

    在TensorFlow1.0时代,采用的是静态计算图,需要先使用TensorFlow的各种算子创建计算图,然后再开启一个会话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.

    二 、静态计算图

    TensorFlow1.0 中的静态计算图

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

    TensorFlow 1.0静态计算图范例(运行需要相应的tensorflow 1.0版本,理解就好)

    1. import tensorflow as tf
    2. # 定义计算图
    3. g = tf.Graph()
    4. with g.as_default():
    5. # placeholder 为占位符,执行会话时候指定填充对象
    6. x = tf.placeholder(name='x', shape=[], dtype=tf.string)
    7. y = tf.placeholder(name='y', shape=[], dtype=tf.string)
    8. z = tf.string_join([x,y], name='join', separator=' ')
    9. # 执行计算题
    10. with tf.Session(graph=g) as sess:
    11. print(sess.run(fetchers=z, feed_dict={x: 'hello', y: 'world!'}))

    输出结果:

    b'hello world!'

    TensorFlow2.0 中的静态计算图

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

    和tensorflow 1.0 版本类似,第一步定义计算图,第二步在会话中执行计算图。现在一般不这么使用。

    1. import tensorflow as tf
    2. # 定义计算图
    3. graph = tf.compat.v1.Graph()
    4. g = tf.compat.v1.Graph()
    5. with g.as_default():
    6. x = tf.compat.v1.placeholder(name='x', shape=[], dtype=tf.string)
    7. y = tf.compat.v1.placeholder(name='y', shape=[], dtype=tf.string)
    8. z = tf.compat.v1.string_join([x,y], name='join', separator=' ')
    9. # 执行计算图
    10. with tf.compat.v1.Session(graph = g) as sess:
    11. # fetches的结果非常像一个函数的返回值,而feed_dict中的占位符相当于函数的参数序列。
    12. print(sess.run(fetches = z,feed_dict = {x: 'hello', y: 'world!'}))
    13. print(z)

    输出结果:

    b'hello world!'
    Tensor("join:0", shape=(), dtype=string)

    三、 动态计算图

    在TensorFlow2.0中,使用的是动态计算图和Autograph.

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

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

    现在来执行上面的代码,来看看是不是简单得多:

    1. # 动态计算图在每个算子处都进行构建,构建后立即执行
    2. x = tf.constant("hello")
    3. y = tf.constant("world")
    4. z = tf.strings.join([x,y],separator=" ")
    5. tf.print(z)
    6. print(z)

    输出结果:

    hello world
    tf.Tensor(b'hello world', shape=(), dtype=string)
    

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

    1. def strjoin(x, y):
    2. z = tf.strings.join([x, y], separator=' ')
    3. tf.print(z)
    4. return z
    5. result = strjoin(tf.constant('你好'), tf.constant('世界 !'))
    6. print(result)

    输出结果:

    你好 世界 !
    tf.Tensor(b'\xe4\xbd\xa0\xe5\xa5\xbd \xe4\xb8\x96\xe7\x95\x8c \xef\xbc\x81', shape=(), dtype=string)

    四、TensorFlow2.0的Autograph

    动态计算图运行效率相对较低。

    可以用@tf.function装饰器将普通Python函数转换成和TensorFlow1.0对应的静态计算图构建代码。

    在TensorFlow1.0中,使用计算图分两步,第一步定义计算图,第二步在会话中执行计算图。

    在TensorFlow2.0中,如果采用Autograph的方式使用计算图,第一步定义计算图变成了定义函数,第二步执行计算图变成了调用函数。

    不需要使用会话了,一些都像原始的Python语法一样自然。

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

    1. import tensorflow as tf
    2. # 使用autograph构建静态图
    3. @tf.function
    4. def strjoin(x,y):
    5. z = tf.strings.join([x,y],separator = " ")
    6. tf.print(z)
    7. return z
    8. result = strjoin(tf.constant("hello"),tf.constant("world"))
    9. print(strjoin)
    10. print(result)
    11. print(strjoin._stateful_fn._function_cache.primary)

    输出结果:

    hello world
    
    tf.Tensor(b'hello world', shape=(), dtype=string)
    OrderedDict([(CacheKey(input_signature=('UUTd7sTd7suDu', None), parent_graph=None, device_functions=(), colocation_stack=(), in_cross_replica_context=False, variable_policy=None, xla_context_id=0), )])

    从第一行的输出知道自定义函数已经被包装成了一个Function类,
    从源码实现来看,在第一次调用自定义函数时,Function类会创建一个FuncGraph,并将自定义函数中的OP(操作符Operator) 注册到FuncGraph中

    保存日志

    1. import logging
    2. import logging.handlers
    3. import os
    4. LOG_FILE = "test_log.log"
    5. logging.basicConfig(filename=LOG_FILE,
    6. filemode="w",
    7. format="[%(levelname)s] %(asctime)s [%(filename)s:%(lineno)d, %(funcName)s] %(message)s",
    8. level=logging.INFO,
    9. encoding="utf-8")
    10. time_hdls = logging.handlers.TimedRotatingFileHandler(LOG_FILE,
    11. when='D',
    12. interval=1,
    13. backupCount=7,
    14. encoding="utf-8") # 每天备份一个文件,且只保留7天的日志
    15. logging.getLogger().addHandler(time_hdls)
    16. result = strjoin("hello","world")
    17. result2 = strjoin('你好', '世界')
    18. logging.info(result)
    19. logging.info(result2)

    随后可以启动tensorboard来进行可视化
    %load_ext tensorboard
    %tensorboard --logdir ./test_log.log/

  • 相关阅读:
    ORA-1142 signalled during: ALTER DATABASE END BACKUP...
    LVS负载均衡群集
    模拟业务流程+构造各种测试数据,一文带你测试效率提升80%
    JavaScript设计模式(七):架构型设计模式-Widget模式
    SSM甜品店系统计算机毕业论文java毕业设计选题源代码
    数据仓库与数据挖掘概述
    C语言典型例题28
    《SpringBoot篇》23.SpringBoot整合JavaMail实现发送邮件详解
    一步一步认知机器学习
    【C++高阶】3.2 vector容器
  • 原文地址:https://blog.csdn.net/m0_51816252/article/details/126864355