[Tensorflow实战Google深度学习框架]笔记2

  本系列为Tensorflow实战Google深度学习框架知识笔记,仅为博主看书过程中觉得较为重要的知识点,简单摘要下来,内容较为零散,请各位指出,共同进步。  

  2017-11-06

  [第三章] Tensorflow入门

  1. Tensorflow计算模型---计算图

  计算图是Tensorflow中最基本的一个概念,Tensorflow中的所有计算都会被转化为计算图上的节点。Tensorflow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

  在Tensorflow程序中,系统会自动维护一个默认的计算图,通过tf.get_default_graph函数可以获取当前默认的计算图。Tensorflow还支持通过tf.Graph()函数来生成新的计算图,

  不同计算图上的张量和运算都不会共享。

  Tensorflow中的计算图不仅仅可以用来隔离张量和计算,它还提供了管理张量和计算的机制。计算图可以通过tf.Graph.device函数来指定运行计算的设备,这为Tensorflow使用GPU提供了机制。

  如: g = tf.Graph()

     with g.device(\'/gpu:0\'):

      result = a + b

  下面的程序可以将加法计算跑在GPU上。

  有效地管理Tensorflow程序中的资源也是计算图的一个重要功能。在一个计算图中。可以通过集合(Collection)来管理不同类别的资源。比如通过tf.add_to_collection函数可以将资源加入一个或多个集合中,然后通过tf.get_collection获取一个集合里面的所有资源。这里的资源可以是张量,变量或者运行Tensorflow程序所需要的队列资源等等。

  2. Tensorflow数据模型---张量

  在Tensorflow程序中,所有的数据都通过张量的形式来表示。从功能的角度上看,张量可以被简单理解为多维数组。但张量在Tensorflow中的实现并不是直接采用数组的形式,它只是对Tensorflow中运算结果的引用,在张量中并没有真正保存数字,它保存的是如何得到这些数字的计算过程。

  一个张量主要保存了三个属性:名字(name),维度(shape)和类型(type)。张量的第一个属性名字(name)不仅是一个张量的唯一标识符,它同样给出了这个张量是如何计算出来的,张量的第二个属性是张量的维度(shape),这个属性描述了一个张量的维度信息,张量的第三个属性是类型(type),每一个张量都会有一个唯一的类型。

  张量的使用主要分为两大类,第一类是对中间计算结果的引用。第二类是当计算图构造完成之后,张量可以用来获得计算结果,也就是得到真实的数字。

  3. Tensorflow运行模型---会话

  会话拥有并管理Tensorflow程序运行时的所有资源,当所有计算完成之后需要关闭会话来帮助系统回收资源,否则就可能出现资源泄漏的问题。

  Tensorflow中使用会话的模式一般有两种,第一种模式需要明确调用会话生成函数和关闭会话函数。

  如:sess = tf.Session()

    sess.run()

    sess.close()

  第二种可以通过Python的上下文管理器来使用会话。只要将所有的计算放在"with"的内部就可以,当上下文管理器退出时会自动释放所有的资源。

  如:with tf.Session() as sess:

      sess.run()

  Tensorflow提供了一种在交互式环境下直接构建默认会话的函数,这个函数就是tf.InteractiveSession,使用这个函数会自动将生成的会话注册为默认会话。

  如:sess = tf.InteractiveSession()

    print(result.eval())

    sess.close()

  可以通过ConfigProto Protocol Buffer来配置需要生成的会话。下面给出了通过ConfigProto配置会话的方法:

  config = tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)

  sess1 = tf.InteractiveSession(config=config)

  sess2 = tf.Session(config=config)

  通过ConfigProto可以配置类似并行的现成数,GPU分配策略,运算超时时间等参数。在这些参数中,最常使用的有两个。第一个是allow_soft_placement,这是一个bool型的参数,当它为True的时候,在以下任意一个条件成立的时候,GPU上的运算可以放到CPU上进行:

    1) 运算无法在GPU上执行。

    2) 没有GPU资源(比如运算被指定在第二个GPU上执行,但是机器只有一个CPU)。

    3)运算输入包含对CPU计算结果的引用。

  这个参数的默认值为False,但是为了使得代码的可移植性更强,在有GPU的环境下这个参数一般会被设置为True。不同的GPU驱动版本可能对计算的支持有略微的区别,通过将allow_soft_placement参数设置为True,当某些运算无法被当前GPU支持时,可以自动调整到CPU上,而不是报错。类似的,通过将这个参数设置为True可以让程序在拥有同数量的GPU机器上顺利运行。

  第二个使用得比较多的配置参数是log_device_placement。这也是一个bool型的参数,当它为True时日志将会记录每个节点被安排在了哪个设备上以方便调试。而在生产环境中将这个参数设为False可以减少日志量。

  4. Tensorflow实现神经网络

  使用神经网络解决分类问题主要可以分为以下四个步骤:

  1) 提取问题中实体的特征向量作为神经网络的输入,不同的实体可以提取不同的特征向量。

  2) 定义神经网络的结构,并定义如何从神经网络的输入得到输出,这个过程就是神经网络的前向传播算法。

  3) 通过训练数据来调整神经网络中参数的取值,这就是训练神经网络的过程。

  4) 使用训练好的神经网络来预测未知的数据。

  全连接神经网络是因为相邻两层之间任意两个节点之间都有连接。这也是为了将这样的网络结构与卷积层,LSTM结构区分。

  tf.random_normal函数可以通过参数mean来指定平均值,在没有指定时默认为0。通过满足正太分布的随机数来初始化神经网络中的参数是一个非常常用的方法。除了正太分布的随机数,Tensorflow还提供了一些其他的随机数生成器,如下列出了Tensorflow目前支持的所有随机数生成器。

  tf.random_normal---->正太分布

  tf.truncated_normal---->正太分布,但如果随机出来的值偏离平均值超过两个标准差,那么这个数将会被重新随机

  tf.random_uniform---->平均分布

  tf.random_gamma---->Gamma分布

  Tensorflow中所有的变量都会被自动的加入GraphKeys.VARIABLES这个集合。通过tf.all_variables函数可以拿到当前计算图上所有的变量。拿到计算图上所有的变量有助于持久化整个计算图的运行状态。当构建机器学习模型时,比如神经网络,可以通过变量声明函数中的trainable参数来区分需要优化的参数(比如神经网络中的参数)和其他参数(比如迭代的轮数),如果声明变量时参数trainable为True,那么这个变量将会被加入GraphKeys.TRAINABLE_VARIABLES集合。在Tensorflow中可以通过tf.trainable_variables函数得到所有需要优化的参数。Tensorflow中提供的神经网络优化算法会将GraphKeys.TRAINALBE_VARIABLES集合中的变量作为默认的优化对象。

  类似张量,维度(shape)和类型(type)也是变量最重要的两个属性。变量的类型时不可改变的,维度在程序运行中是有可能改变的,但是需要通过设置参数calidate_shape=False。虽然Tensorflow支持更改变量的维度,但是这种用法在实践中比较罕见。

  反向传播算法中每轮迭代选取的数据由Tensorflow的placeholder机制来提供,placeholder相当于定义了一个位置,这个位置中的数据在程序运行时再指定,这样在程序中就不需要生成大量的常量来提供输入数据,而只需要将数据通过placeholder传入Tensorflow计算图。

  总结下训练神经网络的过程,可以分为以下三个步骤:

  1)定义神经网络的结构和前向传播的输出结果。

  2)定义损失函数以及选择反向传播优化的算法。

  3)生成会话(tf.Session)并且在训练数据上反复运行反向传播优化算法。