《TensorFlow:实战Google深度学习框架》笔记

第一章:深度学习简介

在大部分情况下,在训练数据达到一定数量之前,越多的训练数据可以使逻辑回归算法对未知邮件做出的判断越精准。之所以说在大部分情况下,是因为逻辑回归算法的效果除了依赖于训练数据,也依赖于从数据中提取的特征。假设从邮件中抽取的特征只有邮件发送的时间,那么即使有再多的训练数据,逻辑回归算法也无法很好地利用。这是因为邮件发送的时间和邮件是否为垃圾邮件之间的关联不大,而逻辑回归算法无法从数据中习得更好的特征表达。这也是很多传统机器学习算法的一个共同问题。

如何从实体中提取特征,对于很多传统机器学习算法的性能有巨大影响。下图展示了一个简单的例子。通过笛卡尔坐标系和极角坐标系表示数据。同样的数据使用不同的表达方式会极大地影响解决问题的难度。一旦解决了数据表达和特征提取,很多人工智能任务也就解决了90%。

既然人工的方式无法很好地抽取实体中的特征,那么是否有自动的方式呢?深度学习解决的核心问题之一就是自动的将简单地特征组合成更加复杂的特征,并使用这些组合特征解决问题。下图展示了深度学习和传统机器学习在流程上的差异。深度学习算法可以从数据中学习更加复杂的特征表达,使得最后一步权重学习变得更加简单且有效。

神经科学家们发现,如果将小白鼠的视觉神经连接到听觉中枢,一段时间之后小白鼠可以习得使用听觉中枢“看”世界。这说明虽然哺乳动物大脑分为了很多区域,但这些区域的学习机制却是相似的。

深度学习的发展历程

第一个阶段:模仿大脑的学习机理

感知机模型可以根据样例数据学习特征权重。
不足:感知机无法解决线性不可分问题,且计算能力不足以训练多层神经网络

第二个阶段:分布式知识表达和反向传播算法
分布式知识表达大大加强了模型的表达能力,让神经网络从宽度的方向走向了深度的方向。
反向传播算法大幅降低了训练神经网络所需要的时间。
不足:计算资源不足以训练深层神经网络;数据量无法满足训练需要。

第三个阶段:云计算、GPU和海量数据
解决了计算力和数据的问题,深度学习迎来高潮。

深度学习的应用

  1. 计算机视觉:分类,识别,无人驾驶,图像搜索等
  2. 语音识别:siri,同声传译等
  3. 自然语言处理:语言模型、机器翻译、词性标注、实体识别、情感分析等
    核心技术:单词向量word embedding
  4. 人机博弈:AlphaGo系列

深度学习工具


第二章:TensorFlow环境搭建

  1. 依赖的工具包
  2. 安装方式
  3. 样例程序(略)

TensorFlow的主要依赖包

Protocol Buffer和Bazel

Protocol Buffer

Protocol Buffer的作用是将结构化的数据序列化,并从序列化之后的数据流中还原出原来的结构化数据。

与XML、Json等其他工具相比:

  • 序列化为二进制流,而不是字符串
  • XML、Json格式信息包含在数据流中,Protocol Buffer需要先定义数据的格式
  • Protocol Buffer数据流比XML小3-10倍,解析时间快20-100倍

结构化数据:

Protocol Buffer数据格式示例:


Protocol Buffer数据格式一般保存在.proto文件中。

TensorFlow中的数据基本都是通过Protocol Buffer来组织的。

Bazel

Bazel是从Google开源的自动化构建工具,相比传统的makefile,Ant或者Maven,Bazel在速度、可伸缩性、灵活性以及对不同程序语言和平台的支持上都要更加出色。Tensorflow本身以及Google给出的很多官方样例都是通过Bazel来编译的。

  • WORKSPACE文件:定义了对外部资源的依赖关系
  • BUILD文件:找到需要编译的目标

在编译出来的结果中,bazel-bin目录下存放了编译产生的二进制文件以及运行该二进制文件所需要的所有依赖关系。

Tensorflow安装方式

  • Docker:可移植性最强,但对GPU支持有限,且对本地开发环境的支持不够友好
  • Pip:最方便,但无法修改Tensorflow本身
  • 源码:最灵活,但比较繁琐,一般只有修改tensorflow护着需要支持特殊GPU才会被用到

第三章 Tensorflow入门

本章介绍Tensorflow的计算模型、数据模型和运行模型,以了解Tensorflow的工作原理。并用Tensorflow实现一个神经网络的计算流程。

Tensorflow计算模型:计算图

计算图是Tensorflow中最基本的一个概念,Tensorflow中的所有计算都被被转化为计算图上的节点。

Tensorflow是一个通过计算图的形式来描述计算的编程系统。Tensor即张量,Flow指计算图。Tensorflow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

为了建模方便,tf将常量转化成一种永远输出固定值的运算。

tf自动维护一个默认的计算图,如果没有特意指定,tf会将定义的计算自动转化为默认计算图上的节点。

除了默认的计算图,也可以用tf.Graph生成新的计算图,不同计算图的张量和运算不会共享。

计算图可以通过tf.Graph.device函数指定运行计算的设备。

有效的整理tf程序中的资源也是计算图的一个重要功能。可以通过集合来管理不同类别的资源。体乳通过tf.add_to_collection将资源加入一个或多个集合中,然后通过tf.get_collection获取一个集合里面的所有资源。这里的资源可以是张量、变量或者运行tf程序所需要的队列资源等。tf自动管理了一些最常用的集合:

Tensorflow数据模型:张量

张量是tf管理数据的形式。

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

执行上面的代码,并不会得到加法的结果,而是对结果的一个引用。
tf的计算都可以通过计算图的模型来建立,而计算图上的每一个节点代表了一个计算,计算的结果保存在张量之中。张量对应了计算图上节点代表的计算结果。

一个张量主要保存三个属性:名字(name),维度(shape)和类型(type)。

  • 张量的命名形式可以是“node:src_output”。其中node为节点的名称,src_output表示来自节点的第几个输出。
  • 维度是张量一个很重要的属性,围绕张量的维度tf给出了很多有用的运算。
  • 每个张量都有一个唯一的类型,tf会对参与运算的所有张量进行类型检查,当发现类型不匹配会报错。如

    报错:

    如果将a指定为实数类型”a=tf.constant([1,2],name=”a”,dtype=tf.float32)”,就不会报错了。不指定类型,tf会给出默认的类型,容易导致类型不匹配问题。tf支持14中不同的类型,主要包括实数(tf.float32,tf.float64)、整数(tf.int8,tf.int16,tf.int64,tf.uinit8)、布尔型(tf.bool)和复数(tf.complex64/tf.conplex128)。

Tensorflow运行模型:会话

计算图和张量分别组织运算和数据,而会话(session)用来执行定义好的运算。会话拥有并管理tf程序运行时的所有资源,当所有计算完成之后需要关闭会话帮助系统回收资源,否则可能出现资源泄露的问题。tf中使用会话的模式一般有两种。

使用这种模式需要明确调用Session.close关闭会话并释放资源。当程序因为异常而退出时,关闭函数可能不会执行导致资源泄露。

通过Python上下文管理器机制,退出时自动释放所有资源。

会话和计算图有类似的机制,但tf不会自动生成默认的会话,而是需要手动指定。默认的会话被指定之后可以通过tf.Tensor.eval函数来计算一个张量的取值。

或者

在交互式环境(比如Python脚本或者Jupyter的编辑器)下,通过设置默认会话的方式来获取张量的取值更加方便。所以tf提供了一种直接构建默认会话的函数tf.InteractiveSession。

无论使用哪种方法都可以通过ConfigProto Protocol Buffer来配置需要生成的会话。

通过ConfigProto可以配置类似并行的线程数、GPU分配策略,运算超时时间等参数。在这些参数中,最常使用的有两个。

  • allow_soft_placement:默认值为False。设为True时,可以在以下情况发生时,把GPU的运算放到CPU上。
    1. 运算无法在GPU上执行
    2. 没有GPU资源(比如指定在第二个GPU,但只有一个GPU)
    3. 运算输入包含对CPU结果的引用
  • log_device_placement:True时日志中会记录每个节点被安排在了哪个设备上以方便调试。在生产环境设为False可以减少日志量。

Tensorflow实现神经网络

Tensorflow游乐场是一个通过网页浏览器就可以训练的简单神经网络并实现了可视化训练的工具。

使用这个工具可以看到神经网络解决分类问题主要分为以下步骤:

  1. 提取问题中实体的特征向量作为神经网络的输入。
  2. 定义神经网络的结构,并定义如何从输入得到输出
  3. 通过训练数据来调整神经网络中参数的取值
  4. 使用训练好的神经网络预测未知的数据

前向传播算法简介

本小节用最简单的全连接网络(区别于卷积网络、LSTM等结构)的前向传播算法介绍。首先需要了解神经元(也称为节点)的结构。

一个节点有多个输入和一个输出,最简单的节点的输出就是对所有输入的加权和,不同输入的权重就是节点的参数。而神经网络的优化过程就是优化节点中参数的值的过程(反向传播算法)。下面给出了一个简单的判断零件是否合格的三层全连接神经网络(全连接神经网络是指相邻两层之间所有节点之间都有连接)。

计算神经网络的前向传播结果需要三部分信息。

  1. 神经网络的输入:从实体中提取的特征向量。上图中的零件长度x1和零件质量x2。
  2. 神经网络的连接结构:神经网络由节点组成,神经网络的结构就是不同节点之间输入输出的连接关系。
  3. 神经元的参数:用W表示神经元的参数。W的上标表明神经网络的层数,下标表明连接节点的编号。如W1,2(1)表示连接x1和a12节点的权重。

有了输入、结构和参数,就可以通过前向传播算法计算神经网络的输出,如图。

其中a11的计算过程

输出y的计算过程

前向传播算法可以表示为矩阵乘法,将输入x1,x2表示为1x2的矩阵x=[x1,x2],W(1)表示为2x3的矩阵

这样通过矩阵乘法就可以得到隐藏层三个节点的向量取值:

类似的输出层:

tf中矩阵乘法的实现非常简单。

![](http://7xt4i9.com2.z0.glb.qiniucdn.com/18-8-9/76520670.jpg) 之后的章节中会继续介绍偏置(bias)、激活函数(activation function)等更复杂的神经元结构,还有卷积神经网络、LSTM等更复杂的神经网络结构。

神经网络参数与Tensorflow变量

本小节介绍tf是如何组织、保存和使用神经网络中的参数的。在tf中,变量的作用是保存和更新神经网络中的参数。tf中的变量需要指定初始值,其中随机初始值最常见。

这段代码调用变量声明函数tf.Variable,在函数中给出了初始化方法。初始值可以是随机数、常数或者通过其他变量的初始值计算得到。tf.random_normal([2,3],stddev=2)会产生一个2x3的矩阵,矩阵的元素是均值为0,标准差为2的随机数。下表列出了tf目前支持的所有随机数生成器。

常量声明方法(比如偏置项:biases=tf.Variable(tf.zeros([3])))

通过其他变量的初始值初始化

以下样例介绍了如何通过变量实现神经网络的参数并实现前向传播的过程。

也可以使用tf.initialize_all_variables函数实现初始化所有变量的过程。

tf中,变量声明函数tf.Variable是一个运算,输出结果是一个张量,所以变量只是一种特殊的张量。下面通过上个案例中计算图中关于w1的操作的可视化结果说明tf.Variable操作在tf中底层是如何实现的。

可以看到w1是一个Variable运算。w1通过一个read操作将值提供给了一个乘法运算(tf.matmul(x,w1)),Assign这个节点的输入为随机数生成函数的输出,输出赋给了变量w1,这样就完成了变量初始化。

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

类似张量,维度和类型也是变量最重要的两个属性。变量类型是不可以改变的,但维度是可能改变的,需要设置参数validate_shape=False,但是更改维度的做法在tf中比较罕见。

通过Tensorflow训练神经网络模型

在神经网络优化算法中,最常用的方法是反向传播算法,本小节主要介绍训练神经网络的整体流程以及Tensorflow对于这个流程的支持。

使用tf实现反向传播算法的第一步是表达一个batch的数据。之前的例子中曾使用常量表达过一个样本,但如果每次迭代都使用一个常量,那么计算图中的常量节点会非常多且利用率很低。为了避免这个问题,tf提供了placeholder机制用于提供输入数据。placeholder相当于定义了一个位置,这个位置中的数据在程序运行时再指定。定义placeholder时,需要指定类型,但是不一定需要维度,因为可以根据提供的数据推导出来。

batch数据例子:


得到前向传播结果后,通过定义好的损失函数计算损失并通过反向传播算法更新神经网络参数。损失函数和反向传播算法将在第四章详细介绍。

完整神经网络样例程序



ipynb github代码

第四章 深层神经网络

本章进一步介绍如何设计和优化神经网络,内容包括深度学习的概念、损失函数、反向传播算法、tf实现反向传播的过程以及神经网络优化中常见的问题。

深度学习与深层神经网络

维基百科对深度学习的定义为“一类通过多层非线性变换对高复杂性数据建模算法的合集”。基本上深度学习就是深层神经网络的代名词。

从定义中可以看出深度学习有两个非常重要的特征:多层和非线性。

猜你喜欢

转载自blog.csdn.net/xiang_freedom/article/details/81448062