【Tensorflow 1.0】—— Graph(图)和Session(会话)

借鉴tensorflow中的Graph(图)和Session(会话)的关系 - 简书

借鉴TensorFlow学习笔记1:graph、session和op - Jiax - 博客园

一、Graph和Session的关系

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

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

  • graph定义了计算方式,是一些加减乘除等运算的组合。它本身不会进行任何计算,也不保存任何中间计算结果。
  • session用来运行一个graph,或者运行graph的一部分。它类似于一个执行者,给graph灌入输入数据,得到输出,并保存中间的计算结果。同时它也给graph分配计算资源(如内存、显卡等)

下图是用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

2.1 定义一个图: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中才能得到其值

2.2 定义多个图:多个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,但通常不建议这么做,原因如下:

  • 运行多个graph需要多个session,而每个session会试图耗尽所有的计算资源,开销太大;
  • graph之间没有数据通道,要人为通过python/numpy传数据。

        事实上,我们可以把所有的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分配合适的计算资源

  • 我们可以把所有的op(op之间不一定相互有联系,如上图中的红烧肉和大盘鸡,两者完全独立)都定义在同一个graph上,Session在执行某个op时,只执行跟该op有关联的其他op,与其不想关的op是不会被执行的。

三、 关于session

        所有的节点计算都在session中完成,tf.Session()是一个大类,使用最多的方法是tf.Session.run()。

通常我们会显示地定义一个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

四、关于op

        graph就是由一系列op构成的。

        一个特殊的op: tf.placeholder()

        placeholder,翻译过来就是占位符。其实它类似于函数里的自变量。比如z = x + y,那么x和y就可以定义成占位符。占位符,顾名思义,就这是占一个位子,平时不用关心它们的值,当你做运算的时候,你再把你的数据灌进去就行了。是不是和自变量很像?看下面的代码:

a = tf.placeholder(tf.float32, shape=[3]) # a是一个3维向量
b = tf.constant([5, 5, 5], tf.float32)
c = a + b
with tf.Session() as sess:
    print sess.run(c, feed_dict = {a: [1, 2, 3]}) # 把[1, 2, 3]灌到a里去

        输出结果是[6, 7, 8]。上面代码中出现了feed_dict的概念,其实就是用[1, 2, 3]代替a的意思。相当于在本轮计算中,自变量a的取值为[1, 2, 3]。其实不仅仅是tf.placeholder才可以用feed_dict,很多op都可以。只要tf.Graph.is_feedable(tensor)返回值是True,那么这个tensor就可用用feed_dict来灌入数据。

        那为什么不直接用tf.constant()去定义呢

        tf.constant()是直接定义在graph里的,它是graph的一部分,会随着graph一起加载。如果通过tf.constant()定义了一个维度很高的张量,那么graph占用的内存就会变大,加载也会变慢。而tf.placeholder就没有这个问题,所以如果数据维度很高的话,定义成tf.placeholder是更好的选择

 

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值