随笔-生活工作点滴

tensorflow中的Graph(图)和Session(会话)

2019-07-07  本文已影响25人  马尔代夫Maldives

基础知识

TensorFlow是一种“符号式编程框架”,首先要构造一个图(graph),然后在会话(Session)上根据这个图做真实的运算(op)。打个比方,graph就像多条生产线,session就像生产者。生产线具有一系列的加工步骤(加减乘除等运算),生产者把原料投进去,就能得到产品。不同生产者都可以使用这条生产线,只要他们的加工步骤是一样的就行。同样的,一个graph可以供多个session使用,而一个session不一定需要使用graph的全部,可以只使用其中的一部分

graph即tf.Graph(),session即tf.Session(),是两个完全独立的概念。

下图是用tensorflow制作大盘鸡和红烧肉的过程,以此为例来说明graph和session的区别:
左图中绿色矩形为数据,黄色圆圈为中间结果,红色圆圈为最终结果,这是一个完整的制作大盘鸡和红烧肉的graph(相当于是一个菜谱),图中每一个独立单元都可以看成是一个op(操作,包括数据)。在tensorflow中只有graph是没法得到结果的,这就像只有菜谱不可能得到红烧肉是一个道理。于是就有了tf.Session(),他根据graph制定的步骤,将graph变成现实。
tf.Session()就相当于一个厨师长,他下面有很多办事的人(Session()下的各种方法),其中有一个非常厉害厨师叫tf.Session.run(),他不仅会烧菜,还会杀猪、酿酒、制作酱料等一系列工作,比如:
我的酱料 = sess.run(酱料):run收到制作“酱料”的命令,于是他看了下graph,需要“酵母”和“大豆”来制作酱料,最终他把酱料制作好了(这里酵母和大豆是graph定义好的,但也可以根据自己的喜好来换)。
我的料酒 = sess.run(料酒,feed_dic={米:泰国籼米}):run又收到要制作“料酒”的命令,而且不用graph规定的“米”来做,需要用“泰国籼米”,没关系,run跑去买了泰国籼米,又把料酒给做了。
我的红烧肉 = sess.run(红烧肉):傍晚,run又收到了做一份完整红烧肉的命令,这下他有的忙了,必须将整个流程走一遍,才能完成个任务。
我的大盘鸡 = sess.run(大盘鸡): 后来,run又收到做大盘鸡的任务,这是一个独立的任务,跟红烧肉没有半点关系,但不影响,他只要按照步骤照做就可以了。

graph和session.jpg

关于Graph

定义一个图:graph

#定义一个graph
g = tf.Graph() 
#默认在g中定义下面op
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b) 

上面就定义了一个graph。tensorflow会默认给我们建立一个graph,所以g = tf.Graph()这句其实是可以省略的。上面的graph包含3个操作(即op),但凡是op,都需要通过session运行之后,才能得到结果。如果你直接执行print(a),那么输出结果是:Tensor("a:0", shape=(), dtype=int32)。执行print(tf.Session().run(a))或with方法,才能得到2。可见,在tensorflow中,即使是最基本的对象Tensor(张量)也需要在Session中才能得到其值,而不能企图通过python一样的方式直接得到其结果。

定义多个图:多个graph

你可以定义多个graph,例如一个graph实现z = x + y,另一个graph实现u = 2 * v

g1 = tf.Graph() #定义一个graph
g2 = tf.Graph() #定义另一个graph
with g1.as_default(): #在指定graph中定义op
    x = tf.constant(2)
    y = tf.constant(3)
    z = tf.add(x, y)
with g2.as_default(): #在指定graph中定义op
    v = tf.constant(4)
    u = tf.mul(2, v)

上述代码定义了两个graph并分别在其中定义了不同的op,但通常不建议这么做,原因如下:

事实上,我们可以把所有的op都定义在一个graph中:

# 没有显示定义graph,系统自动提供一个默认的graph
# 并在其中定义下面op
x = tf.constant(2)
y = tf.constant(3)
z = tf.add(x, y)
v = tf.constant(4)
u = tf.mul(2, v)

从上面graph的定义可以看到,x/y/z是一波,u/v是另一波,二者没有任何交集。这相当于在一个graph里有两个独立的subgraph。当你要计算z = x + y时,执行tf.Session().run(z);当你想计算u = 2 * v,就执行tf.Session().run(u),二者完全独立。但更重要的是,二者在同一个session上运行,系统会均衡地给两个subgraph分配合适的计算资源

关于Session(待完善)

所有的节点计算都在session中完成,tf.Session()是一个大类,使用最多的方法是tf.Session.run()(见:https://www.jianshu.com/writer#/notebooks/29416844/notes/50146577
通常我们会显示地定义一个session来运行graph,通常采用with的方式(推荐),也可用其他方式:

# 以下在一个默认graph中定义了三个op
x = tf.constant(2)
y = tf.constant(3)
z = tf.add(x, y)

# 以下显示启动了一个Session并在其中执行z
with tf.Session() as sess:
    result = sess.run(z)
    print(result)

输出结果是5。

感谢文章:https://www.cnblogs.com/jiaxblog/p/9054051.html

上一篇下一篇

猜你喜欢

热点阅读