图像融合 densefuse python初学 ②

TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

TensorFlow是一种“符号式编程框架”,首先要构造一个图(graph),然后在会话(Session)上根据这个图做真实的运算(op)。

打个比方,graph就像多条生产线,session就像生产者。生产线具有一系列的加工步骤(加减乘除等运算),生产者把原料投进去,就能得到产品。不同生产者都可以使用这条生产线,只要他们的加工步骤是一样的就行。同样的,一个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

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

  • 运行多个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()(见:https://www.jianshu.com/writer#/notebooks/29416844/notes/50146577
通常我们会显示地定义一个session.run来运行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。

=================================================

tensorflow下的Graph中 tf.Operation是一个node,而tf.Tensor是一个edge

以tf.constant(0.0)为例,调用tf.constant(0.0)创建一个单独的tf.Operation,生成值42.0,将其添加到默认图形,并返回一个表示常数的值的tf.Tensor

在没有特别说明的情况下,程序中定义的tf.Operation均是添加进入default_graph中。若使用

graph1=tf.Graph()	# 声明tf.Graph()的一个类实例,即获取一个graph
with graph1.as_default():
	#完成graph1这个计算图中的tf.Operation的定义,即将在这个with所调用的上下文管理器中定义的tf.Operation添加进入声明的tf.Graph实例graph1中
	pass

其实这种方式本质上也是将graph设置为default_graph,所以可以认为,所有的tf.Operation均是添加到default_graph进行的,而这个default_graph是可以设置的。

再说说这个with graph1.as_default():

with会启动一个上下文管理器。所谓上下文管理器,就是在程序执行前将上文中当前所需要的资源准备好,并在结束时被系统回收。

with graph1.as_default()的含义是在这个with启动的上下文管理器中将graph1设置为default_graph,在with启动的上下文管理器内部所定义的tf.Operation则会添加进入当前的default_graph中,也就是graph1中。在整个with代码块结束后,default_graph将会重新设置为之前的,属于全局的graph。

=================================================

TensorFlow——Graph的基本操作

1.创建图

在tensorflow中,一个程序默认是建立一个图的,除了系统自动建立图以外,我们还可以手动建立图,并做一些其他的操作。

下面我们使用tf.Graph函数建立图,使用tf.get_default_graph函数来获取图,使用reset_default_graph对图进行重置。

import tensorflow as tf
import numpy as np


c = tf.constant(1.5)
g = tf.Graph()

with g.as_default():

    c1 = tf.constant(2.0)
    print(c1.graph)
    print(g)
    print(c.graph)

g2 = tf.get_default_graph()
print(g2)

tf.reset_default_graph()
g3 = tf.get_default_graph()
print(g3)

运行结果如下所示:

根据上述的运行结果,c是在刚开始的默认图中建立的,所以打印的结果就是13376A1FE10,和g2获取的默认图的值是一样的,然后使用tf.Graph建立了一个新的图,并添加了变量c1,最后又对图进行了重置,替代了原来的默认图。

在使用reset_default_graph()函数的时候,要保证当前图中资源都已经全部进行了释放,否则将会报错。

2.获取张量

我们可以在图中通过名字得到其对应的元素,比如获取图中的变量和OP等元素。

import tensorflow as tf
import numpy as np

g = tf.Graph()

with g.as_default():
    c1 = tf.constant(2.5, name='c1_constant')
    c2 = tf.Variable(1.5, dtype=tf.float32, name='c2_constant')
    add = tf.multiply(c1, c2, name='op_add')

    c_1 = g.get_tensor_by_name(name='c1_constant:0')
    c_2 = g.get_tensor_by_name(name='c2_constant:0')
    c_3 = g.get_tensor_by_name(name='op_add:0')


    print(c_1)
    print(c_2)
    print(c_3)

在进行测试时,我们为元素添加了变量名,在设置变量名的时候,设置好的名字会自动添加后面的:0字符。一般我们可以将名字打印出来,在将打印好的名字进行回填。

3.获取节点操作

获取节点操作OP的方法和获取张量的方法非常类似,使用get_operation_by_name.下面是运行实例:

import tensorflow as tf
import numpy as np

a = tf.constant([[1.0, 2.0]])
b = tf.constant([[1.0], [3.0]])

tensor_1 = tf.matmul(a, b, name='matmul_1')

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    t1 = tf.get_default_graph().get_operation_by_name(name='matmul_1')
    t2 = tf.get_default_graph().get_tensor_by_name(name='matmul_1:0')
    print(t1)
    print('t1: ', sess.run(t1))
    print('t2: ', sess.run(t2))

在上述的代码中,定义了一个OP操作,命名为matmul_1,在运行时我们将op打印出来,在使用名字后面加上  :0    我们就能得到OP运算的结果的tensor,注意这两者的区别。

我们还可以通过get_opreations函数获取图中的所有信息。此外,我们还可以使用tf.Grapg.as_graph_element函数将传入的对象返回为张量或者op。该函数具有验证和转换功能。

=================================================

数据结构: Graph

图的基础

图是一种(包含若干个节点),每个节点可以连接 0 个或多个元素

两个节点相连的部分称为边(edge)。节点也被称作顶点(vertice)

一个顶点的度(degree)是指与该顶点相连的边(edge)的条数。比如上图中,紫色顶点的度是 3,蓝色顶点的度是 1。

如果所有的边都是双向(译者注:或者理解为没有方向)的,那我们就有了一个无向图(undirected graph)。反之如果边是有向的,我们得到的就是有向图(directed graph)。你可以将有向图和无向图想象为单行道或双行道组成的交通网。

顶点的边可以是从自己出发再连接回自己(如蓝色的顶点),拥有这样的边的图被称为自环

图可以有环(cycle),即如果遍历图的顶点,某个顶点可以被访问超过一次。而没有环的图被称为无环图(acyclic graph)


此外,无环无向图也被称为树(tree)

在图中,从一个顶点出发,并非所有顶点都是可到达的。可能会存在孤立的顶点或者是相分离的子图。如果一个图所有顶点都至少有一条边(译者注:原文表述有点奇怪,个人认为不应该是至少有一条边,而是从任一节点出发,沿着各条边可以访问图中任意节点),这样的图被称为连通图(connected graph)。而当一个图中两两不同的顶点之间都恰有一条边相连,这样的图就是完全图(complete graph)

对于完全图而言,每个顶点都有 图的顶点数 - 1 条边。在上面完全图的例子中,一共有7个顶点,因此每个顶点有6条边。

https://www.cnblogs.com/baby-lily/p/10960054.html

https://blog.csdn.net/weixin_39721347/article/details/89004100

https://www.imooc.com/article/47287

https://www.jianshu.com/p/b636de7c251a

https://blog.csdn.net/ikerpeng/article/details/72844728

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值