目录
静态图的弊端
tensorflow的最初版本是用静态图的方式运行的,在这种方式下,计算图将计算的定义和执行分隔开, 这是一种声明式(declaretive)的编程模型.
静态图的执行模式优点很多,但是在debug时确实非常不方便(类似于对编译好的C语言程序调用,此时是我们无法对其进行内部的调试), 因此有了Eager Execution, 这在TensorFlow v1.5首次引入,在2.0版本中成为了核心API。
引入的Eager Execution模式后, TensorFlow就拥有了类似于Pytorch一样动态图模型能力, 我们可以不必再等到see.run(*)才能看到执行结果, 可以方便在IDE随时调试代码,查看OPs执行结果. 动态图的引入也给写tf代码带来一些新的特性,需要注意。
Eager模式
Eager 模式有点儿类似于python的命令式编程,不需要编译直接运行,非常直观。
Eager execution的基本特性
对 numpy 的支持
eager 模式下对 numpy 的支持很友好,具体特性如下:
- numpy 的操作可以接受 Tensor 作为参数;
- tensorflow 的数学操作会将 python 对象和 numpy 的 arrays 转换成 Tensor;
- tf.Tensor.numpy 方法返回 numpy的ndarray
例如:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 9 10:21:24 2020
@author: lxy_alex@outlook.com
"""
import numpy as np
import tensorflow as tf
tf.compat.v1.enable_eager_execution()
def example_of_tf_and_np():
a = tf.constant([[1,2],[3,4]])
b = tf.add(a,1)
print(a)
print(b)
print('tf\'s multiply: ')
print(a*b)
c = np.multiply(a,b)
print('numpy\'s multiply:')
print(c)
print('transfer tensor a to numpy ndarray from: ')
print(a.numpy())
if __name__ == ‘__main__’:
example_of_tf_and_np()
得到:
tf's multiply:
tf.Tensor(
[[ 2 6]
[12 20]], shape=(2, 2), dtype=int32)
numpy's multiply:
[[ 2 6]
[12 20]]
transfer tensor a to numpy ndarray from:
[[1 2]
[3 4]]
虽然tensorflow的eager模式对tensor 和numpy的多维数据之间有很好的兼容性,但是并不意味着tf.Tensor() 定义的变量与python的其它变量等同。在实际使用中,一定要注意不能混淆了python变量和tf的Tensor对象。
Auto Graph - 动态图
eager模式支持python的控制流,也支持tf的动态流,对于tf的动态流,对于while循环或者类似的循环(也许使用for,if控制),形如:
while x>0:
x = x-1
在tensorflow控制流中可以写为tf.while_loop(…, loop_vars=(x,))的形式。但是,tf.while_loop不能支持无限个变量,同时tensorflow 计算图的效率受到其中while loop循环数量的影响,所有不能随意地使用while loop。
AutoGraph使用静态分析来确定代码修改了哪些符号,以便将它们转换为控制流变量。静态分析通常是在单个函数上执行的——Python的动态特性限制了它跨函数的有效性。
static analysis VS dynamic flow
局部参数的可见域
在函数中的局部变量发生变化后,函数外的主程序那里这个变化是不可见的,类似地,在类定义的方法中,局部变量发生改变的时候,主程序也是不可见的,除非这些变量显式地作为输出参数返回。同理,对于类成员函数内部的参数而言,在函数外也是不可见的。
python collections 数据在tensorflow控制流的使用
tf的控制流支持大多数python数据结构,例如列表,字典和元组,包括collection对象的namedtuple对象,但是在tf的控制流中,这些变量被许是固定结构的,也即是说在loop中,列表不能改变长度,字典不能增加或者减少keys。啥是namedtuple,可以参考:https://docs.python.org/3/library/collections.html#collections.namedtuple
def fn():
l = []
def loop_cond(i):
return i < 10
def loop_body(i):
i = i + 1
l.append(i)
return i,
tf.while_loop(
cond=loop_cond,
body=loop_body,
loop_vars=(0,))
return l
print(fn(