前言:TensorFlow是一种符号式编程框架,首先要构造一个图(graph),然后在这个图上做运算。打个比方,graph就像一条生产线,session就像生产者。生产线具有一系列的加工步骤(加减乘除等运算),生产者把原料投进去,就能得到产品。不同生产者都可以使用这条生产线,只要他们的加工步骤是一样的就行。同样的,一个graph可以供多个session使用,而一个session不一定需要使用graph的全部,可以只使用其中的一部分。
一、Tensorflow的工作流程
- 根据需求,创建计算图Graph
- 开启会话Session,读取数据运行Graph
- 获取结果
二、TensorFlow 几个关键概念:Tensor,Operation,Graph,Session
1.Tensor(数据节点)
(1)Tensor定义
在 TensorFlow 中,所有在节点之间传递的数据都为 Tensor 对象。
Tensor定义:A Tensor is a symbolic handle to one of the outputs of an Operation. It does not hold the values of that operation’s output, but instead provides a means of computing those values in a TensorFlow tf.Session
也就是说,Tensor本身是不存储数据的,创建一个Tensor实际就是声明了一个数据节点。只有开启Session进行运算的时候,才会获取到数据。
(2)Tensor的阶
如下图所示,Rank为0、1、2时分别称为标量、向量和矩阵,Rank为3时是3阶张量,Rank大于3时是N阶张量。这些标量、向量、矩阵和张量里的元素可以是数组,可以是tensor或者其他python基本数据类型。当所有元素类型一致且均为tensor(数组)时,则可将Rank的阶数当做tensor(数组)的阶数。通常我们讨论的数据类型是指元素的数据类型。
Tensor的阶数(3)Tensor的几个重要属性
shape:类似于Numpy中ndarray.shape,比方说一个2行3列的二维矩阵,他的形状就是2行3列。
dtype:类似于Numpy中ndarray.dtype,常用的类型有:
tf.uint8: 8-bit unsigned integer.
tf.int32: 32-bit signed integer.
tf.int64: 64-bit signed integer.
tf.String: String.
tf.float32: 32-bit single-precision floating-point.
tf.float64: 64-bit double-precision floating-point.
name:每个Tensor都必须有name属性。在创建Tensor时,如果用户没有指定name,Tensorflow会自动设置;在同一张Graph中,不会有Tensor重名,当用户设定的name重名时,Tensorlfow会自动加入后缀进行区分。
(4)几种Tensor
- 常量Tensor:值不能改变,最常见的常量创建方式为tf.constant(value, dtype=None, shape=None, name="Const", verify_shape=False),其中value不可少,verify_shape表示常量的形状是否可以被更改,默认不可更改。初此之外还有以下常量的创建方法:
- 变量Tensor:值可以改变,可训练。在神经网络中,变量一般可作为储存权重和其他信息的矩阵,而常量可作为储存超参数或其他结构信息的变量。变量的创建方法如下(变量的创建均需要指定shape,且shape要以list或tuple的形式传入):
- 占位符 placeholder: tf.placeholder(dtype=tf.float32, shape = [2,3],name='b')
为什么要使用tf.placeholder?
因为每一个tensor在graph上都是一个op。当我们将train数据分成一个个minibatch然后传入网络进行训练时,每一个minibatch都将是一个op,这样的话,一副graph上的op未免太多,也会产生巨大的开销;于是就有了tf.placeholder,我们每次可以将 一个minibatch传入到x = tf.placeholder(tf.float32,[None,32])上,下一次传入的x都替换掉上一次传入的x,这样就对于所有传入的minibatch x就只会产生一个op,不会产生其他多余的op,进而减少了graph的开销。
SparseTensor(稀疏张量):定义时只需要定义非0的数,其他的数会自动填充。
#Example: The sparse tensor
2.Operation(计算节点)
将多个Tensor连接在一起,形成新的Tensor。例如tf.add、tf.mul等操作。tensor在graph上也是一个Operation(简称op)。但凡是op,都需要通过session运行之后,才能得到结果。
3.Graph(数据节点+计算节点)
GraphGraph就是由一系列op构成的。具体来说就是由W、b、x等数据节点及Add、MatMul等计算节点共同构成一个Graph。
在Tensorflow中,始终存在一个默认的Graph。如果要将Operation添加到默认Graph中,只需要调用定义Operation的函数(例如tf.add())。如果我们需要定义多个Graph,则需要在with语句中调用Graph.as_default()方法将某个graph设置成默认Graph,于是with语句块中调用的Operation或Tensor将会添加到该Graph中。
import tensorflow as tf#定义一个图:只有一个图时,这个图就是默认图,所有操作都自动添加到这个图中
g = tf.Graph()#tensorflow会默认给我们建立一个graph,这句话可以省略
a = tf.constant(2)#将Operation添加到默认Graph中,只需要调用定义Operation的函数print(a.graph)
print(tf.get_default_graph())#通过调用tf.get_default_graph()访问默认创建的图的位置#定义多个图:需要声明某个操作是定义在哪个图中的
g1 = tf.Graph()
g2 = tf.Graph()
#将某个graph设置成默认Graph,with语句块中调用的Operation或Tensor将会添加到该Graph中
with g1.as_default():x = tf.constant(2)y = tf.constant(3)z = tf.add(x, y)print(x.graph, y.graph, z.graph)print(tf.get_default_graph())with g2.as_default():v = tf.constant(4)u = tf.add(2, v)print(v.graph, u.graph)print(tf.get_default_graph())#e不是定义在with语句里面的,e会包含在tensorflow默认创建的图中。也就是说e与a在同一个图中
e=tf.constant(value=15)
print(e.graph)
如果在创建Session时没有指定Graph,则该Session会加载默认Graph。如果创建了多个Graph,则需要创建不同的Session来加载每个Graph,而每个Graph则可以加载在多个Session中进行计算。
import tensorflow as tf
g1 = tf.Graph()
with g1.as_default():c1 = tf.constant([1.0])
with tf.Graph().as_default() as g2:c2 = tf.constant([2.0])with tf.Session(graph=g1) as sess1:print(sess1.run(c1))
with tf.Session(graph=g2) as sess2:print(sess2.run(c2))# result:
# [ 1.0 ]
# [ 2.0 ]
#如果将上面例子的sess1.run(c1)和sess2.run(c2)中的c1和c2交换一下位置,运行会报错。
# 因为sess1加载的g1中没有c2这个Tensor,同样地,sess2加载的g2中也没有c1这个Tensor。
4.Session(对Graph进行计算)
Tensorflow先构造Graph,然后开启session在这个Graph上做运算。Graph是由一系列op组成。但凡是op,都需要通过session运行之后,才能得到结果。Session的作用就是执行Operation(Tensor也可以看作一种Operation)。
执行Operation有两种方式:
- 调用Session.run()方法: 该方法的定义如下所示,参数fetches便是一个或者多个Operation或者Tensor。
tf.Session.run(fetches, feed_dict=None)
- 调用Tensor.eval()方法: 这个方法接收参数session,用于指定在哪个session中计算。该参数默认为None,表示在默认session中计算。设置默认session有两种方式:
#设置默认session的方式一
import tensorflow as tfa = tf.constant([1.0, 2.0])
b = tf.constant([3.0, 4.0])
c = tf.add(a, b)with tf.Session():#with语句块中的语句print(c.eval())#设置默认session的方式二
import tensorflow as tfa = tf.constant([1.0, 2.0])
b = tf.constant([3.0, 4.0])
c = tf.add(a, b)sess = tf.Session()
with sess.as_default():print(c.eval())
sess.close()
session.run()与tensor.eval()都是开启对Graph的计算,下面比较一下两者:
首先,tensor.eval()只适用于tensor。而session.run()不仅适用于tensor,还可用于没有输出的op。对于tensor,调用session.run()与tensor.eval()是等价的。
import tensorflow as tf
t = tf.constant(42.0)
sess = tf.Session()
#calling t.eval() is equivalent to calling tf.get_default_session().run(t).
with sess.as_default(): # or `with sess:` to close on exitassert sess is tf.get_default_session()assert t.eval() == sess.run(t)
sess.close()
其次,你可以使用session.run()在同一步骤中获取许多张量的值,而tensor.eval()却只能一次获得一个张量的值。
import tensorflow as tft = tf.constant(42.0)
u = tf.constant(37.0)
tu = tf.add(t, u)
ut = tf.add(u, t)sess = tf.Session()
with sess.as_default():tu.eval() # runs one steput.eval() # runs one stepsess.run([tu, ut]) # evaluates both tensors in a single step
sess.close()
参考:
Tensorflow 中eval()和sess.run()的关系
Tensorflow中 Graph和Session的关系
TensorFlow进阶(三)---变量的创建、初始化 - 时间&煮雨~ - 博客园
Tensorflow学习笔记2:About Session, Graph, Operation and Tensor
TensorFlow学习笔记1:graph、session和op - Jiax - 博客园
TensorFlow学习(三):Graph和Session - 谢小小XH - CSDN博客