理解了TensorFlow的框架,才能灵活应用各个模块。TensorFlow主要由三个模型构成:计算模型,数据模型,运行模型。本节主要介绍这三个模型的概念和应用。

<>1. TensorFlow系统架构



<>2. TensorFlow是符号式编程的典型代表

我们知道,现有编程模式主要有两大类:命令式和符号式。很好理解,命令式编程就是一句代码执行一个操作,结果是代码即所得。例如:
a = 1 b = 2 c = a + b print(c)
每一步都会返回操作的结果,而符号式编程不一样,
import tensorflow as tf a = tf.constant(1.0) b = tf.constant(2.0) c = a + b
print(c)
输出:
Tensor("add:0", shape=(), dtype=float32)
并没有直接的输出结果,而是c的数据类型,因为上面只是定义了计算,并没有执行计算。下面加上执行计算的代码。
sess = tf.InteractiveSession() print(c.eval())
此时输出: 3.0

第一句是创建一个会话,第二句得到c的值并打印。这个例子很好的说明了符号式编程的范式:先定义计算,再执行计算。TensorFlow是典型的全符号式编程,因而其编程模式一般都是先定义计算再执行计算。

再TensorFlow中,使用计算图定义计算,使用会话执行计算,整个过程以张量(Tensor)这个数据机构为基础。接下来主要介绍这三个模型:计算模型,数据模型,运行模型。

<>3. 计算模型-计算图

<>3.1 概念


顾名思义,计算图的主要构成是节点和边,它是表达计算的一种方式。计算图中的每一个节点代表一个计算,而节点之间的边描述的是计算之间的依赖关系。事实上TensorFlow这个名字就很好的体现了计算计算图,其中tensor是张量,也就是TensorFlow的数据结构,flow是流,反应了张量之间通过计算相互转换的过程。

<>3.2 使用

前面说过,计算图主要用来定义计算,而这个过程和命令式编程没有什么区别,只是每一句程序都会定义一个计算,返回的是该计算的张量,而不是计算结果。
在计算图的使用中,需要注意两点:不同计算图上的张量和运算都不会共享,变量作用域机制。
(1)TensorFlow中可以定义不同的计算图,并且不同的计算图之间的张量个运算都不会共享。这里引用一个例子[1]:
import tensorflow as tf g1 = tf.Graph() with g1.as_default(): #此时将g1设为默认图 #
在计算图个g1中定义变量"v",并设置初始值为0 v = tf.get_variable("v",
initializer=tf.zeros_initializer()(shape=[1])) g2 = tf.Graph() with
g2.as_default(): #此时将g2设为默认图 # 在计算图个g2中定义变量"v",并设置初始值为1 v =
tf.get_variable("v", initializer=tf.ones_initializer()(shape=[1]))
#在计算图g1找那个读取变量"v"的取值 with tf.Session(graph=g1) as sess:
tf.global_variables_initializer().run() #初始化 with tf.variable_scope("",
reuse=True): #设置图g1中v为共享变量,共享变量域名为空,定义过v后reuse才能为True
#在计算图g1中,变量"v"的取值应该为0,所以会输出[0.] print(sess.run(tf.get_variable("v"))) #返回v的值
#在计算图g2找那个读取变量"v"的取值 with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run() #初始化 with tf.variable_scope("",
reuse=True): #设置图g2中v为共享变量,共享变量域名为空,定义过v后reuse才能为True
#在计算图g2中,变量"v"的取值应该为0,所以会输出[1.] print(sess.run(tf.get_variable("v"))) #返回v的值
这也说明,计算是基于计算图的。

(2)在(1)中的实例变量v可以共用,是因为在不同的计算图上计算的,在同一个计算图上对于变量命名是有
一套规则的,必须遵循TensorFlow规定的变量作用域。

<>4. 数据模型-张量


张量是TensorFlow中的数据结构,也就是管理数据的形式。可简单的理解为多维数组,其中零阶张量为标量,一阶便是向量,n阶则为n维数组。但是张量在TensorFlow中的具体实现方式并不是直接采用numpy中类似的多维数据的形式,它实际上是对于TensorFlow中运算的引用。也就是说,张量并没有真正保存数字,它保存的是得到这些数字的过程。还是2.
中的例子:
import tensorflow as tf a = tf.constant(1.0) b = tf.constant(2.0) c = a + b
print(c)
输出:
Tensor("add:0", shape=(), dtype=float32)
返回的add:0
是说c这个张量引用的是add运算的第一个结果,也就是c这个节点的本质name是add:0,同时我们也可以看到,张量有三个属性:name,shape,
dtype,对应的是它的名称,维度和类型

<>4.1 name


name在TensorFlow中是张量的唯一标识,由于其遵循TensorFlow的变量管理机制,所以它也能表达出这个张量是如何计算出来的,例如上面的例子。name一般表达为node:src_output的形式,node是节点,也就是运算,src_output表示此张量是该运算的第几个输出。
直接通过tensor.name <http://xn--tensor-hb9ls98jgy9byxa.name> 获取其name值.

通过name获取张量值:
import tensorflow as tf # get the name b = tf.Variable(4.0, name='a')
print(b.name) # get the tensor be name c =
tf.get_default_graph().get_tensor_by_name("a:0") print(c)
<>4.2 shape

描述张量的维度信息,获取维度有两种方式:
x.shape 和x.get_shape()
import tensorflow as tf a = tf.constant([[1,2,3],[3,5,6]]) print(a.shape)
print(a.get_shape())
输出:
(2, 3) (2, 3)
转换为list:
a.get_shape().as_list()
<>4.3 dtype

张量的类型,获取方式:
a.dtype
import tensorflow as tf a = tf.constant([[1,2,3],[3,5,6]]) print(a.dtype)
<>5. 运行模型-会话(session)


TensorFlow通过计算图定义运算,通过会话管理运算。会话拥有并管理tensorflow程序运行时的所有资源。需要注意的是,一般而言,在程序运行完成之后,需要显示的关闭会话来回收系统资源。TensorFlow中使用会话的方式一般有两种。
(1)需要显示调用生成函数和关闭函数来生成和关闭会话
# 此处定义了很多计算 # 此处开始运行计算 # 创建会话 sess = tf.Sesssion() # 运行计算 sess.run(...) # 关闭会话
sess.close()
(2)不需要显示关闭,这种模式有两种方法。
a. 直接使用交互函数
tf.InteractiveSession()
由于该函数是为ipython等脚本环境设计的,运行完成或者遭受意外退出都会直接关闭会话,不需要再代码中显示关闭。

b. 通过python提供的上下文管理机制
# 此处定义了很多计算 # 此处开始运行计算 # 创建会话 with tf.Sesssion() as sess: # 运行计算 sess.run(...)
在运行完with里的所有代码后退出with的时候会自动关闭,也无需显式关闭。


这里需要注意的是,除了采用sess.run(需要得到结果的张量)这种模式引用张量的结果,还可以通过tensor.eval()这种方式计算结果。但这两种方式有很大的区别:tensor.eval()需要指定默认会话。
sess.run(…)这种方式是最普通的方式,任何场合都适用,但是适用tensor.eval() 的场合是一下几种。
(1)通过tf.InteractiveSession()方式创建会话
tf.InteractiveSession()不仅创建会话而且指定了当前会话为默认会话,所以能用eval()函数。
(2)显式指定默认会话
tf.Session()函数只有创建会话的功能,并不能将该会话设置为默认会话,需要显示的设置默认会话。
sess = tf.Session() with sess.as_default(): print(x.eval())
或者在eval() 函数里指定会话。
sess = tf.Session() print(x.eval(session=sess))
最后请记住:张量是一种数据结构,是运算结果的引用,并不是真正的计算结果。只有在会话中通过sess.run() 或者x.eval() 来运算并返回运算结果。

<>6. 参考文献

[1] https://blog.csdn.net/gaoyueace/article/details/78984583
<https://blog.csdn.net/gaoyueace/article/details/78984583>
[2] tensorflow实战google深度学习框架