Tensorflow编程系统
Tensorflow工具或者说深度学习自己就是一个连贯紧密的系统。通常的系统是一个自治独立的、能实现复杂功能的总体。系统的主要任务是对输入进行处理,以获得想要的输出结果。咱们以前见过的不少系统都是线性的,就像汽车生产工厂的流水线同样,输入->系统处理->输出。系统内部由不少单一的基本部件构成,这些单一部件具备特定的功能,且须要稳定的特性;系统设计者经过特殊的链接方式,让这些简单部件进行链接,以使它们之间能够进行数据交流和信息互换,来达到相互配合而完成具体工做的目的。node
对于任何一个系统来讲,都应该拥有稳定、独立、能处理特殊任务的单一部件;且拥有一套良好的内部沟通机制,以让系统能够健康安全的运行。python
现实中的不少系统都是线性的,被设计好的、不能进行更改的,好比工厂的流水线,这样的系统并不具有自我调整的能力,没法对外界的环境作出反应,所以也就不具有“智能”。编程
深度学习(神经网络)之因此具有智能,就是由于它具备反馈机制。深度学习具备一套对输出所作的评价函数(损失函数),损失函数在对神经网络作出评价后,会经过某种方式(梯度降低法)更新网络的组成参数,以指望系统获得更好的输出数据。安全
因而可知,神经网络的系统主要由如下几个方面组成:网络
- 输入
- 系统自己(神经网络结构),以及涉及到系统自己构建的问题:如网络构建方式、网络执行方式、变量维护、模型存储和恢复等等问题
- 损失函数
- 反馈方式:训练方式
定义好以上的组成部分,咱们就能够用流程化的方式将其组合起来,让系统对输入进行学习,调整参数。由于该系统的反馈机制,因此,组成的方式确定须要循环。session
而对于Tensorflow来讲,其设计理念确定离不开神经网络自己。因此,学习Tensorflow以前,对神经网络有一个总体、深入的理解也是必须的。以下图:Tensorflow的执行示意。ide
那么对于以上所列的几点,什么才是最重要的呢?我想确定是有关系统自己所涉及到的问题。即如何构建、执行一个神经网络? 在Tensorflow中,用计算图来构建网络,用会话来具体执行网络。深刻理解了这两点,我想,对于Tensorflow的设计思路,以及运行机制,也就略知一二了。函数
- 图(tf.Graph):计算图,主要用于构建网络,自己不进行任何实际的计算。计算图的设计启发是高等数学里面的链式求导法则的图。咱们能够将计算图理解为是一个计算模板或者计划书。
-
会话(tf.session):会话,主要用于执行网络。全部关于神经网络的计算都在这里进行,它执行的依据是计算图或者计算图的一部分,同时,会话也会负责分配计算资源和变量存放,以及维护执行过程当中的变量。工具
接下来,咱们主要从计算图开始,看一看Tensorflow是如何构建、执行网络的。oop
计算图
在开始以前,咱们先复习一下Tensorflow的几种基本数据类型:
tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False) tf.Variable(initializer, name) tf.placeholder(dtype, shape=None, name=None)
复习完毕。
graph = tf.Graph() with graph.as_default(): img = tf.constant(1.0, shape=[1,5,5,3])
以上代码中定义了一个计算图,在该计算图中定义了一个常量。Tensorflow默认会建立一张计算图。因此上面代码中的前两行,能够省略。默认状况下,计算图是空的。
在执行完img = tf.constant(1.0, shape=[1,5,5,3])之后,计算图中生成了一个node,一个node结点由name, op, input, attrs组成,即结点名称、操做、输入以及一系列的属性(类型、形状、值)等组成,计算图就是由这样一个个的node组成的。对于tf.constant()函数,只会生成一个node,但对于有的函数,如tf.Variable(initializer, name)(注意其第一个参数是初始化器)就会生成多个node结点(后面会讲到)。
那么执行完img = tf.constant(1.0, shape=[1,5,5,3])后,计算图中就多一个node结点。(由于每一个node的属性不少,我只表示name,op,input属性)
继续添加代码:
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1])
代码执行后的计算图以下:
须要注意的是,若是没有对结点进行命名,Tensorflow自动会将其命名为:Const、Const_一、const_2......。其余类型的结点类同。
如今,咱们添加一个变量:
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1]) kernel = tf.Variable(k)
该变量用一个常量做为初始化器。咱们先看一下计算图:
如图所示:
执行完tf.Variable()函数后,一共产生了三个结点:
- Variable:变量维护(不存放实际的值)
- Variable/Assign:变量分配
- Variable/read:变量使用
图中只是完成了操做的定义,但并无执行操做(如Variable/Assign结点的Assign操做,因此,此时候变量依然不可使用,这就是为何要在会话中初始化的缘由)。
咱们继续添加代码:
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1]) kernel = tf.Variable(k) y = tf.nn.conv2d(img, kernel, strides=[1,2,2,1], padding="SAME")
获得的计算图以下:
能够看出,变量读取是经过Variable/read来进行的。
若是在这里咱们直接开启会话,并执行计算图中的卷积操做,系统就会报错。
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1]) kernel = tf.Variable(k) y2 = tf.nn.conv2d(img, kernel, strides=[1,2,2,1], padding="SAME") with tf.Session() as sess: sess.run(y2)
这段代码错误的缘由在于,变量并无初始化就被使用,而从图中清晰的能够看到,直接执行卷积,是回溯不到变量的值(Const_1)的(箭头方向)。
因此,在执行以前,要进行初始化,代码以下:
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1]) kernel = tf.Variable(k) y2 = tf.nn.conv2d(img, kernel, strides=[1,2,2,1], padding="SAME") init = tf.global_variables_initializer()
执行完tf.global_variables_initializer()函数之后,计算图以下:
tf.global_variables_initializer()产生了一个名为init的node,该结点将全部的Variable/Assign结点做为输入,以达到对整张计算图中的变量进行初始化。
因此,在开启会话后,执行的第一步操做,就是变量初始化(固然变量初始化的方式有不少种,咱们也能够显示调用tf.assign()来完成对单个结点的初始化)。
完整代码以下:
img = tf.constant(1.0, shape=[1,5,5,3]) k = tf.constant(1.0, shape=[3,3,3,1]) kernel = tf.Variable(k) y2 = tf.nn.conv2d(img, kernel, strides=[1,2,2,1], padding="SAME") init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) # do someting....
会话
在上述代码中,我已经使用会话(tf.session())来执行计算图了。在tf.session()中,咱们重点掌握无所不能的sess.run()。
一个session()中包含了Operation被执行,以及Tensor被evaluated的环境。
tf.Session().run()函数的定义:
run( fetches, feed_dict=None, options=None, run_metadata=None )
tf.Session().run()函数的功能为:执行fetches参数所提供的operation操做或计算其所提供的Tensor。
run()函数每执行一步,都会执行与fetches有关的图中的全部结点的计算,以完成fetches中的任务。其中,feed_dict提供了部分数据输入的功能。(和tf.Placeholder()搭配使用,很舒服)
参数说明:
- fetches:能够是图中的一个结点,也能够是一个List或者字典,此时候返回值与fetches格式一致;该参数还能够是一个Operation,此时候返回值为None。
- feed_dict:字典格式。给模型输入其计算过程当中所须要的值。
当咱们把模型的计算图构建好之后,就能够利用会话来进行执行训练了。
在明白了计算图是如何构建的,以及如何被会话正确的执行之后,咱们就能够愉快的开始Tensorflow之旅啦。