第1章-TensorFlow基础
1.1 TensorFlow概要
TensorFlow官方网站 链接
TensorFlow github网站 链接
TensorFlow模型仓库网站 链接
TensorFlow既是一个实现机器学习算法的接口,同时也是执行机器学习算法的框架。
TensorFlow使用数据流式图来规划计算流程的,它可以将计算映射到不同硬件和操作系统平台。
1.2 TensorFlow编程模型简介
1.2.1 核心概念
TensorFlow中的计算可以表示为一个有向图,或者称为计算图,其中的每一个计算操作将作为一个节点,节点和节点之间的连接称为边。
计算图的每一个节点可以有任意个输入和任意个输出,每一个节点描述了一种运算操作,节点可以算是运算操作的实例化。在计算图边中流动的数据被称为张量(tensor)。
session是用户使用TensorFlow时的交互式接口。
1.2.2 实现原理
TensorFlow有一个重要的组件是client即客户端,它通过session的接口和master以及多个work相连。其中每一个work可以与多个硬件设备相连,并负责管理这些硬件。而master则负责指导所有的work按照流程执行计算图。
TensorFlow分为单机好分布式两种。
TensorFlow为CPU和GPU提供了管理设备的对象接口,每一个对象负责分配、释放设备的内存,以及执行节点的运算核。
在只有一个硬件设备的情况下,计算图会按照依赖关系被顺序执行。
当有多个设备时,情况变得复杂,难点有二:
- 每一个节点该让什么硬件设备来执行
- 如何管理节点之间的数据通信。
第一个问题,TensorFlow设计了一套为节点分配资源的策略。
第二个问题,在多个设备上,计算图会被划分为许多子图,子图通过发送节点和接收节点通信。
1.2.3 拓展功能
- TensorFlow原生支持自动求导,但是也会给TensorFlow的优化带来麻烦。
- TensorFlow还支持单独执行子图。
- TensorFlow支持计算图的控制流。(if/while etc.)
- input node可以让用户直接输入文件系统路径
- 队列是TensorFlow任务调度的一个重要特性
- 容器是TensorFlow中一种特殊的管理长期变量的机制
1.2.4 性能优化
- TensorFlow能自动识别重复计算,并改写计算图
- 可以巧妙的安排计算的顺序来改善数据传输和内存占用的问题
- 支持异步计算
- 第三方高度优化库,eg. cuDNN,cuda-convenet
- 支持对数据精度进行压缩
TensorFlow提供了三种不同的加速神经网络训练的并行计算模式
-
数据并行
-
模型并行
-
流水线并行
2 TensorFlow和其他深度学习框架的对比 18
2.1 主流深度学习框架对比 18
2.2 各深度学习框架简介 20
TensorFlow
TensorFlow是相对高阶的机器学习库,用户㐓方便地用它设计神经网络结构,而不必为了追求高效率的实现亲自写C++或者CUDA代码。
TensorFlow另外一个特点是灵活的移植性。
TensorFlow还提供了TensorBoard,TensorBoard是TensorFlow的一组web应用,用来监控TensorFlow的运行过程,或可视化计算图。
caffe
caffe的主要优势有以下几点:
- 容易上手,网络结构都是以配置文件形式定义,不需要用代码设计网络
- 训练速度快,能够训练state-of-the-art的模型与大规模的数据。
- 组件模块化,可以方便的拓展到新的模型和学习任务上。
caffe的一大优势是拥有大量的训练好的经典模型(AlexNet/VGG/Inception)乃至其他state-of-the-art(ResNet等)的模型。收藏在它的model zoo里。
Theano
Theano的主要优势如下:
- 集成numpy,可以直接使用numpy的ndarray,API接口学习成本低。
- 计算稳定性好
- 动态的生成C或者cuda代码,用以编译成高效率的机器代码。
Theano是一个完全基于python的符号计算库。
Torch
Torch是LuaJIT上的一个高效的科学计算库,支持大量的机器学习算法,同事以GPU上的计算优先。
Lasagne
Lasagne是一个基于Theano的轻量级的神经网络库。
Keras
Keras是崇尚极简、高度模块化的神经网络库,使用python实现,并可以同事运行在TensorFlow和Theano上。
MXNet
MXNet是DMLC开发的一款开源的、轻量级、可移植的、灵活的深度学习库,它让用户可以混合使用符号编程模式和指令式编程模式来最大化效率和灵活性。
DIGITS
DIGITS不是一个标准的深度学习库,它可以算是caffe的高级封装。
CNTK
CNTK是微软研究院开源的深度学习框架。
CNTK设计是性能导向的。
Deepelearning4J
Deepelearning4J是一个基于java和scala的开源的分布式深度学习库,其核心目标是创建一个即插即用的解决方案原型。
chainer
chainer特性描述:
- powerfull 支持cuda计算
- flexible 支持多种前馈神经网络
- intuitive 前馈计算可以引入python的各种控制流
leaf
leaf是一个基于Rust语言的直观的跨平台的深度学习乃至机器智能框架。
DSSTNE
github网址 链接
DSSTNE是亚马逊开源的稀疏神经网络框架,在训练稀疏的数据时具有很大优势。
3 TensorFlow第一步 39
3.1 TensorFlow的编译及安装 39
-
install anconda
link -
CPU version
conda install tensorflow -
GPU version
conda install tensorflow-gpu
3.2 TensorFlow实现SoftmaxRegression识别手写数字 46
导入数据
MNIST是一个非常简单的机器视觉数据集,由几万张28x28像素的手写数字组成,这些图片只包含灰度信息。
|
|
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
(55000, 784) (55000, 10)
(10000, 784) (10000, 10)
(5000, 784) (5000, 10)
可以看到数据集中,训练集有55000个样本,测试集有10000个样本,验证集有5000个样本。
这里的数据全部丢弃了图片的二维结构信息,只是把一张图片变成了一个很长的一维向量。
我们可以使用matplotlib把一维数据还原为原来的图像。如下所示。
|
|
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
)
训练数据(55000, 784),第一维是图片的编号,第二维是图片中像素点的编号。
对10个种类的标签进行了onehot编码,如上所示,[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] 代表为7
准备好数据以后,接下来就要设计算法了
这里使用了一个叫做softmax regression的算法来训练分类模型。
当我们处理分类任务时,通常需要使用softmax regression模型。即使后面章节中的CNN或者RNN,如果是分类模型,最后一层同样也是softmax regression。
它的工作原理很简单,将可以判定为某类的特征想加,然后将这些特征转化为判定为这一类的概率。
这些特征可以通过一些简单的方法得到,比如对所有像素求一个加权和,而权重是根据数据自动学习、训练出来的。比如某一个像素的灰度值大代表可能是数字n的概率越大。
如下公式:
featurei=∑jWijxj+bi
其中i为第i类,j代表一张图片的第j个像素。bi是bias。
接下来计算所有特征的softmax,简单的说就是计算一个exp函数,然后再进行标准化(让所有类别的输出的概率值和为1)。
softmax(x)=normalize(exp(x))
其中判定为第i类的概率是:
softmax(x)_i=exp(x)∑jexp(xj)
可以用下面一行简洁的表达:
y=softmax(Wx+b)
cross_entropy的定义如下:
Hy′(y)=−∑iy′ilog(yi)
代码
https://github.com/sundaygeek/tensorflow-in-action/blob/master/3_2_HelloWorld.py
总结
从上面的例子,我们可以总结一下整个流程。
- 定义算法公式,也就是神经网络forward时的计算
- 定义loss,选定优化器,并指定优化器优化loss
- 迭代地对数据进行训练
- 在测试集或者验证集上对准确率进行评测。
第4章-TensorFlow实现自编码器及多层感知机
4.1 自编码器简介
深度学习在早期一度被认为是一种无监督的特征学习,模仿了人脑的对特征逐层抽象提取的过程。这其中两点很重要,一是无监督学习,即我们不需要标注数据就可以对数据进行一定程度的学习,这种学习是对数据内容的组织形式的学习,抽取的是频繁出现的特征,二是逐层抽象,特征是需要不断抽象的,就像人总是从简单基础的概念开始学习,再到复杂的概念。
简单的特征是可以不断抽象转化为高一级的特征的,那我们如何找到这些结构呢,然后如何抽象呢?如果我们有狠毒哦标注的数据,就可以训练一个深层的神经网络。如果没有标注的数据呢?这种情况下,我们依然可以使用无监督的自编码器来提取特征。自编码器,就是可以使用自身的高阶特征编码自己。自编码器也是一种神经网络,它的输入和输出是一直的,它借助稀疏编码的思想,目标是使用稀疏的一些高阶特征重新组合来重构自己。因此特点非常明显,第一,期望输入和输出一直,第二,希望使用高阶特征重构自己,而不是复制像素点。
自编码器通常希望使用少量稀疏的高阶特征来重构输入,所以我们可以加入几种限制:
- 如果限制中间隐含层节点的数据量,比如让中间银行曾节点的数量小于输入/输出节点的数据量,就相当于一个降维过程。
- 如果给数据加入噪声,那么就是denoising antuoencoder去噪自编码器,我们将从噪声中学习数据的特征。
去噪自编码器中最常使用的是加性高斯噪声AGN,其结构图如下:
当然也可以使用masking noise,即有随机遮挡的噪声,这样图像中的一部分像素被置为0,模型需要从其他像素结构推测出这些被遮挡的像素是什么,因此模型依然需要学习图像中抽象的高阶特征。
如果自编码器的隐含层只有一层,其原理类似于主成分PCA。
Hinton教授提出了基于深度信念网络(DBN),由多层RBM堆叠而成。我们可能很难直接训练极深的网络,但是可以用无监督的朱岑个训练提取特征,将网络的权重初始化到一个比较好的位置,辅助后面的监督训练。在DBN模型中,含有多个隐含层,每一个隐含层都是限制性玻尔兹曼RBM(一种具有特殊连接分布分神经网络)。DBN训练时,需要先对每两层见进行无监督的预训练,这个过程相当于一个多层的自编码器,可以将整个网络的权重初始化到一个理想的分布。最后通过反向传播算法调整模型权重,这个步骤会使用经过标注的信息来做监督性的分类训练,也解决了网络过深带来的梯度弥散问题。简单的说,hinton的思路是先用自编码器的方法进行无监督的预训练,提取特征并初始化权重,然后使用标注信息进行监督式的训练。
4.2 TensorFlow实现自编码器
https://github.com/sundaygeek/tensorflow-in-action/blob/master/4_2_AutoEncoer.py
至此,去噪自编码器实现就全部完成了。自编码器作为一种无监督学习的方法,它与其他无监督学习的主要不同是,它不是对数据进行聚类,而是提取其中最有用、最频繁出现的高阶特征,根据这些高阶特征重构数据。
4.3 多层感知机简介
为了拟合复杂的场景,需要隐含层,但是过深的神经网络会遇到过拟合、参数难以调试、梯度弥散等问题。对于这些问题我们徐亚哦很多的trick来解决。
-
过拟合是指在模型预测准确率在训练集上升高了,但是在测试集上却小江了,通常意味着泛化能力不好,模型只是记忆了当前数据的特征,不具备推广能力。
Hilton团队提出来一个dropout方法,它的大致思路是在训练时,将神将网络的某一层的输出节点数据随机丢弃一部分。dropout也算是一种bagging方法,可以理解为每次丢弃节点数据是对特征的一种采样。 -
参数难以调试是另外一个痛点,尤其是SGD参数。
-
梯度弥散,之前的sigmoid容易在层间传播误差,直到ReLU出现才比较完美解决了梯度弥散问题。ReLU是一个简单的非线性函数y=max(0,x)
ReLU相对于sigmoid主要变化有三个:
- 单侧抑制
- 相对宽阔的兴奋边界
- 稀疏**性
当然,深加工年网络的额输出层一般都还是sigmoid函数,因为它最接近概率输出分布。
说了那么多,隐含层到底有什么用呢。
隐含层代表性的功能是可以解决XOR问题。没有隐含层的神经网络是线性的,这是早期神经网络的致命缺陷,当引入了隐含层并使用了非线性的**函数后我们可以使用曲线划分样本,解决XOR异或函数的分类问题。神经网络的隐含层越多,就可以对原有特征进行越抽象的变换,模型的拟合能力越强,这就是多层感知机MLP的功能所在。
4.4 TensorFlow实现多层感知机
加入隐含层
https://github.com/sundaygeek/tensorflow-in-action/blob/master/4_4_MLP.py
在测试集上可以达到大约98%的准确率,相当于第三章的92%提升了不少。
第5章-TensorFlow实现卷积神经网络CNN
5.1 卷积神经网络简介
卷积神经网络CNN最初是为了解决图像识别等问题设计的,当然现在的应用已经不限于图像和视频,也可以用于时间序列信号,比如音频信号、文本数据等。
在深度学习出现之前,必须借助SIFT、HoG等算法提取出有效而丰富的特征,再集合SVM等机器学习算法进行图像识别。
CNN作为一个深度学习架构被提出来最初的诉求是降低对图像数据预处理的要求,以及避免复杂的特征工程。CNN最大的特点是在于卷积的权值共享结构,可以大幅减少神经网络的参数量,方式过拟合的同时又降低了神经网络模型的复杂度。
卷积神经网络的历史
感受野 —> 神经认知机(S-cells/C-cells)
卷积神经网络可以利用空间结构关系减少需要学习的参数量,从而提高方向传播算法的训练效率。在卷积神经网络中,第一个卷积层直接接受图像像素的输入,每一个卷积操作只处理一小块图像,进行卷积变化后再传到后面的网络,每一层卷积都会提取数据中最有效的特征。这种方法可以提取到图像中最基本的特征,而后再进行组合和抽象形成更高阶的特征。
一般卷积神经网络由多个卷积层构成,每个卷积层中通常会进行如下几个操作。
- 图像通过多个不同的卷积核的滤波,并加偏置,提取出局部特征,每一个卷积核会映射出一个新的2D图像
- 将前面卷积核的滤波输出结果,进行非线性的**函数处理。目前最常见的是使用ReLUctant函数,而以前sigmoid函数用的比较多。
- 再**函数的结果再进行池化操作(即降采样),目前一般是使用最大池化,保留最显著的特征,并提高模型的畸变容忍能力。
这几个步骤构成了最常见的卷积层,当然也可以加上一个LRN(局部响应归一化层)层,目前非常流程的trick还有batch normalization等。
一个卷积层中可以有多个不同的卷积核,而每一个卷积核都对应一个滤波后映射的新图像,同一个新图像中每一个像素都来自完全相同的卷积核,这就是卷积核的权值共享。我们为什么要共享卷积核的权值参数呢?答案很简单,降低模型复杂度,减轻过拟合并降低计算量。
每一个卷积核滤波得到的图像就是一类特征的映射,即一个Feature map。
参数量和隐含节点个数或者图片大小无关,只跟卷积核的大小有关,这就是所谓的权值共享。
总结一下就是,卷积神经网络的要点就是局部连接、权值共享、池化层中的降采样。其中局部连接和权值共享降低了参数量,使得训练复杂度大大下降,并减轻了过拟合。同事权值共享还赋予了卷积网络对平移的容忍性,而池化层降采样则进一步降低了输出参数量,并赋予模型对轻度形变的容忍性,提高了模型的泛化能力。
LeNet5
LeNet5是最早的深层卷积神经网络之一
LeNet5特性有如下几点:
- 每个卷积层包含三部分,卷积、池化和非线性**函数
- 使用卷积提取空间特征
- 降采样的平均池化层
- 双曲正切tanh或者s型sigmoid的**函数
- MLP多层感知机作为最后的分类器
- 层与层之间的稀疏连接减少计算复杂度
LeNet5结构图如下所示:
5.2 TensorFlow实现简单的卷积网络
https://github.com/sundaygeek/tensorflow-in-action/blob/master/5_2_CNN_MNIST.py
5.3 TensorFlow实现进阶的卷积网络
Cifar-10数据集
本节使用的卷积网络模型,我们使用了一些新技巧:
①对weight进行了L2的正则化
②我们对图片进行了翻转、随机剪切等数据增强,制造了更多的样本
③在每个卷积-最大池化层后面使用了LRN层,增强了模型的泛化能力。
https://github.com/sundaygeek/tensorflow-in-action/blob/master/5_3_CNN_CIFAR10.py
可以观察到,设计CNN主要就是安排卷积层、池化层、全连接层的分布和顺序,以及其中超参数的设置、trick的使用等等。设计性能良好的CNN是有一定规律可循的,但是要想针对某个问题设计最合适的网络结构,是需要大量实践摸索的。
数据增强在我们训练中作用很大,它可以给单幅图增加多个副本,提高图片的利用率,防止对某一张图片结构的学习过拟合。
数据增强大大增加了样本量,而且数据量的大小恰恰是深度学习最看重的,深度学习可以在图像识别上领先其他算法的一大因素就是他对海量数据的利用效率非常高。用其他算法,可能在数据量大到一定程度,准确率就不再上升了,而深度学习只要提供足够多的样本,准确率基本可以持续提升,所以说它是最适合大数据的算法。
第6章-TensorFlow实现经典卷积神经网络
本章介绍四种经典的卷积神经网络,分别是Alexnet/VGGNet/Google Inception Net/ResNet。
6.1 TensorFlow实现AlexNet
AlexNet主要使用到的新技术点如下:
1、成功使用ReLU作为CNN的**函数,并验证其效果在较深的网络超过了sigmoid,成功解决了sigmoid在网络较深时的梯度弥散问题。
2、训练时使用dropout随机忽略一部分神经元,以避免模型过拟合。
3、在CNN中使用重叠的最大池化
4、提出了LRN层,对局部神经元的活动创建竞争机制
5、使用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵计算。
6、数据增强,随机从256*256的原始图像中截取224*244大小的区域
https://github.com/sundaygeek/tensorflow-in-action/blob/master/6_1_AlexNet.py
CNN训练过程(即backward过程)通常比较耗时,而且不像预测过程(即forward过程),训练通常需要经过很多遍数据,进行大量的迭代。因此应用CNN主要的瓶颈在于训练,用CNN做预测问题不大。目前TensorFlow已经支持IOS和Android系统中运行,所以在手机上使用CPU进行人脸识别或者图片分类已经非常方便了,并且响应速度也很快。
至此,AlexNet的TensorFlow实现已经完成了。
6.2 TensorFlow实现VGGNet
VGGNet在训练时候有一个小技巧,先训练级别A的简单网络,再复用A网络的权重来初始化后面的几个复杂模型,这样训练收敛的速度很快。
在预测时,VGG采用mutl-scale的方法,将图像scale到一个尺寸Q,并将图片输入卷积网络计算。然后最后一个卷积层使用滑窗的方式进行分类预测,将不同窗口的分类结果平均,再将不同尺寸Q的结果平均得到最后结果,这样可提高图片数据的利用率并提升预测准确率。同事在训练中,VGGNet还使用multi-scale方法做图像增强,将原始图像缩放到不同尺寸S,然后在随机裁剪224*224的图片,这样能增加很多数据量,对于防止模型过拟合有很多不错的效果。
同时,作者在对比各级网络时,总结了以下几个缺点:
1、LRN层作用不大
2、越深网络效果越好
3、1*1的卷积也是很有效果的,但是没有3*3卷积好,大一些的卷积可以学习更大空间特征。
https://github.com/sundaygeek/tensorflow-in-action/blob/master/6_2_VGG.py
6.3 TensorFlow实现Google inception net
inception V1降低参数量的目的有两个:
1、参数越多模型越庞大,需要供模型学习的数据量就越大,而高质量的数据非常昂贵
2、参数越多,耗费的计算资源也越大
inception V1参数少但是效果好的原因除了模型层数更深、表达能力更强外,还有两点,一是去除了最后的全连接层,使用全局平均池化层来取代他,二是inception V1中精心设计的inception module提高了参数的利用效率。不过inception V1比NIN(论文network in network)更进一步的是增加了分支网络,NIN则主要是级联的卷积层和MLPConv层,一般来说,卷积层要提升表达能力,主要依靠增加输出通道数,但是副作用是计算量增大和过拟合。每一个输出通道对应一个滤波器,同一个滤波器共享参数,只能提取一类特征,因此一个输出通道只能做一种特征处理。而NIN中MLPConv则拥有更强大的能力,允许在输出通道之间组合信息,因此效果明显。
人脑神经元的连接是稀疏的,因此研究者认为大型神经网络的合理的连接方式应该也是稀疏的,稀疏结构非常适合神经网络的一种结构,尤其对于非常大型、非常深的神经网络,可以减轻过拟合并降低计算量。
inception network的主要目标就是找到最优的稀疏结构单元,论文中提到其稀疏结构基于Hebbian原理,即神经反射活动的持续与重复会导致神经元连接稳定性的持久提升,当两个神经元细胞A和B距离很近,并且A参与了对B重复、持续的兴奋,那么某些代谢变化会导致A将作为能使B兴奋的细胞。
受Hibbian原理的启发,另一个文章也提出,如果数据集的概率分布可以被一个很大很稀疏的神经网络所表达,那么构筑这个网络的最佳方法是逐层构筑网络:将上一层高度相关的节点聚类,并将聚类出来的每一个小簇连接到一起。如下图。
inception V2提出了著名的batch normalization方法
inception V3主要有两个方向的改造:一是引入了factorization into small convolutions,二是inception V3优化了inception module的结构。
inception V4主要结合了微软的ResNet。
本节主要实现inception V3
代码: https://github.com/sundaygeek/tensorflow-in-action/blob/master/6_3_InceptionNet.py
inception V3作为一个极深的卷积神经网络,拥有非常精妙的设计和构造,整个网络的结构和分支非常复杂。inception V3有很多设计CNN的思想和Trick值得借鉴:
1、 factorization into small convolution很有效,可以降低参数量、减轻过拟合,增加网络非线性的表达能力
2、卷积网络从输入到输出,应该让图片尺寸逐渐缩小,输出通道数逐渐增加,即让空间结构简化,将空间信息转化为高阶抽象的特征信息。
3、inception module用多个分支提取不同抽象程度的高阶特征的思路很有效,可以丰富网络的表达能力。
6.4 TensorFlow实现ResNet
第7章-TensorFlow实现循环神经网络RNN及Word2Vec
第8章-TensorFlow实现深度请强化学习
第9章-TensorBoard-多GPU并行及分布式并行
第10章-TF.Learn从入门到精通
第11章-TF.Contrib的其他组件
posted on 2018-07-22 12:30 sundaygeek 阅读(...) 评论(...) 编辑 收藏