深度学习基础

机器学习的本质就是寻找最优模型。

而深度学习是机器学习的一个大分支,深度学习的概念源于对人工神经网络的研究,深度学习的基本结构(也即模型)是深度神经网络。

感知机是最简单的一种人工神经网络,是一种二元线性分类器。感知机抽象于生物神经细胞,为了模拟神经细胞行为,与之对应的感知机基础概念被提出,如权重(突触)、偏置(阈值)及激活函数(细胞体)。

感知机:

深度学习基础_第1张图片

不同的输入a与其对应的权重w相乘后全部加和,再与偏置值相加后送入激活函数,经激活函数后得到该感知机的输出。在人工神经网络中,规定神经元函数只能对输入变量(指向它的节点的值)线性组合后的结果进行一次非线性变换(激活函数)。这里的激活函数可以采用Sigmoid函数,Sigmoid函数的输出值在0到1之间:

感知机也被用来特指单层人工神经网络,以区别于多层感知机。感知机无法处理线性不可分问题。什么叫线性不可分?举个例子,二维平面上有两类点,无法用一条一维直线将其完全分开;N维空间中有两类点,用N-1维的分隔超平面无法将两类点完全分开,就叫做线性不可分。

感知机(神经元)之间采用不同的连接方式,也就构成了不同的网络结构。每个神经元都拥有自己的权重值和偏置值。权重值和偏置值构成了这个网络的参数。

简单的前馈神经网络:

深度学习基础_第2张图片

给定参数值可以定义一个神经元,也即定义一个函数;再给定网络结构,就可以定义一个神经网络,也即一组函数。

深度神经网络中的深度意味着神经网络的层数很多,神经网络中第一层是输入层,最后一层是输出层,中间数层是隐藏层,每一层都由若干神经元构成。

我们可以选择应用Softmax层作为输出层,Softmax层可以将输出层神经元的输出值进行处理,使其总和为1。这在分类场景,判定属于哪类的概率最大时,提供了方便,也使得数据更容易被理解。

已经选定了深度学习的基本结构,也就是深度神经网络,接下来要谈的是对神经网络输出结果好坏的量化评估以及如何找到最佳的参数值。

在初始参数条件,一般神经网络的输出结果并不完全正确,我们需要对其参数进行优化,要优化参数,首先要度量误差,误差来源于预测结果与实际结果的距离,比如对于手写数字识别,给定一张写着『2』的图片,最理想的输出是,只有2对应的那个神经元输出为1,其它输出均应该为0。我们可以选择计算每个神经元的输出与理论结果的误差,然后将其加和,由此得到了我们对神经网络的优化目标,也即通过调整参数让整个损失函数的函数值最小。

那我们该如何确定最佳参数值呢?遍历肯定不行,如果D层,每层N个神经元,那复杂度就是N的D次方。终究还是要选择梯度下降方法。

梯度下降法参数迭代公式

η是学习速率,η后面的式子是损失函数对该参数变量的偏导数。

深度学习网络分类

如前所述,深度学习指的是一类广泛的机器学习技术和架构,其特点是采用多层的非线性信息处理方法,这种方法在本质上是分层的。根据这些结构和技术不同的应用领域,如合成/生成或识别/分类,我们可以大致把这些结构分为三类:

  • 无监督的或生成式学习的深度网络:针对模式分析和合成任务,用于在没有目标类标签信息的情况下捕捉观测到的或可见数据的高阶相关性。各种文献中的无监督特征或表达学习指的就是这一类深度网络。当用于生成模式时,它也可以用来描述可见数据和其相关分类的联合分布概率,此时它具有可以利用的类别标签,而且这些类别标签被看做是可见数据的一部分。在后一种情况中,利用贝叶斯准则可以把生成学习网络转换为判别式学习网络。

  • 有监督学习的深度网络:直接提供用于模式分类目的的判别能力,它的特点是描述了可见数据条件下的后验分布(条件概率分布)。这种有监督的学习,目标类别标签总是以直接或间接形式给出,所以它们也被称作判别式深度网络。

  • 混合深度网络:目标是判别式模型,往往以生成式或无监督深度网络的结果作为重要辅助,可以通过更好地优化和正则化上个类别中的深度网络来实现,也可以通过对第一个类别所述的深度生成式或无监督深度网络的参数进行估计时,使用判别式准则来实现。

在其他文献里,一般将深度机器学习技术分为深度判别式模型(深度神经网络DNN、递归神经网络RNN、卷积神经网络CNN等)和生成式/无监督模型(受限玻尔兹曼机RBM、深度信念网络DBN、深度玻尔兹曼机DBM、正则化的自编码器等),然而这种二元分类方法忽略了通过深度学习研究所获得的重要观点,即生成式和无监督学习如何通过更好地进行正则化与优化,来大幅提高DNN和其他深度判别式和监督学习模型的训练效果。同时,无监督学习的深度网络并不一定必须是概率模型,也不一定能从模型中得到有意义的采样。深度有监督的学习模型适合复杂系统的端到端学习;而深度无监督学习模型,尤其是概率生成模型,更容易理解,更容易嵌入领域知识,更容易组合,对不确定性进行处理。

下面先只讲无监督和生成式学习深度网络。

无监督学习是指在学习过程中不使用特定任务的监督信息(如目标类别标签)。这一类深度网络大多可以通过从网络中采样来有效生成样本,因此是生成式模型,例如RBM、DBN、DBM和广义除噪自编码器。然而这一类别中的有些网络采样并不容易,因而本质上并不是生成式的,例如稀疏编码网络和原始形式的深度自编码器。

生成式或无监督深度网络有多个子类:

一类是各种自编码器及其堆叠形式,具体的说,在除噪自编码器中,输入向量首先被『破坏』,例如,随机选择一定比例的输入并把它们设为零,或加入高斯噪声,然后调整参数,使隐层编码结点重构出原始的、未损坏的输入数据,调整参数所使用的准则包括原始输入与重建输入的最小均方误差和KL散度准则。将未损坏数据进行转换,获得编码表示,并将其作为下一层堆叠自编码器的输入。

另一类有生成能力的深度无监督模型是深度玻尔兹曼机(DBM),DBM包含很多隐变量层,并且同一层变量之间没有连接。DBM是玻尔兹曼机(BM)的一个特例。当DBM的隐层数为1时,我们就得到了受限玻尔兹曼机(RBM),RBM与DBM一样,没有隐层到隐层和显层到显层的连接。RBM的主要优点是,通过组合许多RBM,把上一层RBM的特征激励作为下一层的训练数据,可以高效的对隐层进行学习,这样组合也即得到了深度信念网络(DBN)。

还有两类,一种是和积网络(SPN),另一种是无监督学习模式下的RNN。

自编码器

深度自编码器是一类特殊的无分类标签的深度神经网络。其输出向量与输入向量同维,常按照输入向量的某种形式,通过隐层学习一个数据的表示或对原始数据进行有效编码。值得注意的是,这种自编码器是一种不利用类标签的非线性特征提取方法。就方法本身而言,这种特征提取的目的在于保留和获得更好的信息表示,而不是执行分类任务,尽管有时这两个目标是相关的。

一个典型的自编码器拥有一个表示原始数据或者输入特征向量的输入层;一个或多个表示特征转换的隐层;一个跟输入层匹配、用于信息重构的输出层。当隐层数目大于1时,这个自编码器就被视为深层结构。隐层的维度可以小于(当目标是特征压缩)或大于(当目标是映射特征匹配更高维的空间)输入层的维度。

如果我们在自动编码器的基础上加上L1的规则限制(L1主要是约束每一层中的节点中大部分都要为0,只有少数不为0,稀疏约束项),我们就可以得到稀疏自动编码方法。也就是上面提到的特征压缩,如果隐藏节点比可视节点(输入、输出)少的话,被迫的降维,自编码器会自动习得训练样本的特征(变化最大,信息量最多的维度),所谓稀疏性,就是对一对输入,隐藏节点中被激活的节点数(输出接近1)远远小于被抑制的节点数目(输出接近0)。那么使神经元大部分的时间都是被抑制的限制被称作稀疏性限制。

另外提一下降噪自编码器,原理很简单,降噪自编码器与自编码器的区别在于,降噪自编码器在原本自编码器的输入上加上了噪声,然后希望通过训练输出去除噪声后的原数据。

栈式自编码器是一个由多层稀疏自编码器组成的神经网络,由于其隐层数目大于1,所以可被认定为是一种深度自编码器。

在栈式自编码器中,前一层的自编码器的输出作为其后一层自编码器的输入。对于一个n层栈式自编码器的编码过程就是,按照从前向后的顺序执行每一层自编码器的编码步骤。

假设我们要训练一个4层的神经网络模型用于分类任务,网络结构如下:

 

深度学习基础_第3张图片

栈式自编码器的训练

整个过程分为两个阶段,一个是无监督预训练阶段(pre-training),另一个是有监督微调阶段。预训练阶段实际上就是一层一层的按照原先训练稀疏自编码器的方法训练每一层的参数。

在预训练阶段,首先,我们要采用稀疏自编码网络,先训练从输入层到H1层的参数:

 

深度学习基础_第4张图片

训练完毕后,我们去除解码层,只留下从输入层到隐藏层的编码阶段。

接着我们训练从H1到H2的参数,我们把无标签数据的H1层元素的激活值,作为H2层的输入层,然后再进行自编码训练:

 

深度学习基础_第5张图片

最后训练完毕后,再去除H2的解码层,如此重复,可以训练更高层的网络,这就是逐层贪婪训练的思想。

训练完H2之后,我们就可以接分类层softmax,用于多分类任务:

 

深度学习基础_第6张图片

以上的过程就是所谓的无监督预训练。后面接着就是利用上面的参数作为网络的初始值,继续进行神经网络的训练了。

玻尔兹曼机

首先是玻尔兹曼分布,其分布的概率公式如下:


玻尔兹曼分布概率公式

pi为量子态i的几率,εi为量子态i的能量,k为玻尔兹曼常数,T为系统温度,M为系统可具有的量子态的总数。

可以看到,εi越大,pi越小,也即物理意义为,在保守力场作用下,低能量的状态比高能量的状态拥有更高的分布几率,举个例子,一个大盒子里放有若干个球,球总是倾向于先占据盒子的底部,即重力势能低的位置,也即处于稳态。

然后是BM,BM是玻尔兹曼机,玻尔兹曼机是一种随机神经网络(同时也是递归神经网络),描述一个随机网络主要需要确定两点。

第一个是这个随机网络的概率分布函数,由于网络节点的取值状态是随机的,从贝叶斯网络的观点来看,要描述整个网络,需要三种概率分布,分别是联合概率分布、边缘概率分布(边缘概率分布的边缘源于它是一组概率的加和,通常被放在表的边缘,P(A)=sum(P(B)*P(A|B)+P(C)*P(A|C)))和条件概率分布。

第二个是这个随机网络的能量函数,随机神经网络根植于统计力学,受统计力学的启发,引入了能量函数。能量函数是描述整个系统状态的一种测度,系统越有序或概率分布越集中,系统的能量越小。反之,系统越无序或者概率分布越趋向于均匀分布,则系统的能量越大(与前面讲过的熵类似)。能量函数的最小值,也就对应了系统的稳态,一般情况下,我们就是要找到系统的稳态,也就是能量函数的最小值。

没有特定限制连接方式的玻尔兹曼机目前为止并没有在机器学习的实际问题中起到什么作用,只是理论上显得有趣。

接下来是受限玻尔兹曼机,图示如下:


深度学习基础_第7张图片

包含三个可见单元和四个隐单元的受限玻尔兹曼机示意图(不包含偏置节点)

RBM与前馈神经网络不一样,RBM在可见层和隐层间的连接方向是不确定的,值可以进行双向传播;且可见层与隐层,层间完全连接,而层内没有连接,也即二分图(不受限玻尔兹曼机隐层单元间存在连接,使之成为递归神经网络)。

标准的受限玻尔兹曼机由二值(布尔/伯努利)隐层和可见层单元组成,权重矩阵W中的每个元素指定了隐层单元hj和可见层单元vi之间连接的权重值(受限玻尔兹曼机每条边必须连接一个隐单元和可见单元),此外对于每个可见层单元vi有偏置ai,对每个隐层单元hj有偏置bi。前面在讲述玻尔兹曼机时提到过,我们要确定两部分内容,一个是联合概率分布、边缘概率分布和条件概率分布,另一个是能量函数。给出了前面的定义,我们先给出受限玻尔兹曼机的能量函数:

更换其为矩阵表示:

根据能量函数,我们进一步给出受限玻尔兹曼机中隐层和可见层之间的联合概率分布:

边缘概率分布(通过对所有隐层配置求和得到):

由于受限玻尔兹曼机是一个二分图,所以隐层单元的激活在给定可见单元取值的情况下是条件独立的,所以条件概率分布:


可见层对隐层


隐层对可见层

单个节点的激活概率为:

 

和:

 

σ为Sigmoid函数。

上面的过程是不是与我们在《浅谈机器学习基础》文中推导LR目标函数的过程有些相似?先利用Sigmoid函数表示出每个节点的激活概率,接下来最大化训练集V的生成概率,训练RBM也是同理:

 

训练受限玻尔兹曼机,即最优化权重矩阵W,使训练集V的生成概率最大,常采用的算法叫做对比分歧(contrastive divergence,CD)算法。这一算法在梯度下降的过程中使用吉布斯采样完成对权重的更新,与训练前馈神经网络中利用反向传播算法(BP)类似。

首先简单说一下什么是吉布斯采样(Gibbs),当积分、期望、联合概率分布很难计算出来(NP问题)的时候,我们利用条件概率产生符合分布的样本,用于估计分布的期望,边缘分布;是一种在无法精确计算情况下,用计算机模拟的方法。

之后是CD-k算法,CD算法的大概思路是,从任意一个样本开始,用经过k次吉布斯采样得到的样本来近似梯度的计算,然后依照梯度去更新参数,与前面讲过的梯度上升/下降算法原理相同。

CD-k算法的具体过程借用别人文章中的截图来描述:

深度学习基础_第8张图片

CD-k算法

对所有的样本都进行k次吉布斯采样,图中蓝色的两个sample函数,就是进行吉布斯采样的过程,sample_h_given_v(v,W,a,b)做的事情是这样的(sample_v_given_v(h,W,a,b)类似):
qj=P(hj|v),j=1,2,…,nh,产生一个[0,1]的随机数rj,对每一个hj,如果rj<qj,则hj=1,否则hj=0。也即qj这个条件概率越大,越接近1,那hj为1的概率就越大,也即根据条件概率进行吉布斯采样。

整个RBM的训练过程如下:

深度学习基础_第9张图片

然后是DBN,DBN也即深度信念网络,深度信念网络可使用多个RBM堆叠而成,并可使用梯度下降法和反向传播算法(BP)进行调优(使用BP对整个DBN微调,对RBM的无监督预训练独立用CD算法)。

具体的说,在讲自动编码器的时候,我们举了一个逐层贪婪预训练方法的例子,这种无监督逐层预训练是一种通用技术,也就是说,不仅前面的自编码器可以逐层预训练,RBM堆叠起来的DBN也可以进行无监督的逐层预训练,方法与自编码器的训练过程类似,主要分为如下两步:

第一步:分别单独无监督的训练每一层RBM网络,确保特征向量映射到不同特征空间时,都尽可能多地保留特征信息。

举个例子,隐含层RBM H可以看做是RBM H+1的可见层。第一个RBM的输入层即是整个网络的输入层,逐层贪婪预训练的工作模式如下:

  • 通过CD算法对所用训练样本训练第一个RBM
  • 将第一个RBM的隐含层作为第二个RBM的输入层数据进行训练,同样采用CD算法
  • 对所有层重复上面的过程
  • 和栈式自编码器一样,通过预训练后,网络堆叠一个或多个层间全连接的RBM隐含层进行扩展,这构成了一个可以通过反向传播进行微调的多层感知机。

第二步:在DBN的最后一层设置BP网络,接受RBM的输出特征向量作为它的输入特征向量,有监督地训练实体关系分类器。每一层RBM网络只能确保自身层内权值对该层特征向量映射达到最优,并不是对整个DBN的特征向量映射达到最优,所以反向传播网络还将错误信息自顶向下传播至每一层RBM,微调整个DBN网络。

每次训练都使当前RBM隐层激活概率无限接近于可见层,实际上,这样的贪婪过程达到了近似的最大似然学习,而且这个学习过程不需要标签信息,用的是可见层输入作为调整依据,所以是无监督的。

RBM网络训练模型的过程可以看做对一个深层BP网络权值参数的初始化,使DBN克服BP网络因随机初始化权值参数而容易陷入局部最优和训练时间过长的问题点。

上述训练DBN的过程,第一步叫做预训练,第二步叫做微调。最上面有监督学习的那一层,根据具体的应用可以换成任何分类器模型,不必是BP网络。

这个过程和栈式自编码器很相似,只是用RBM将自编码器进行替换,用CD算法训练RBM替代BP算法训练自编码器。

这里再提一下反向传播算法。

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。

BP算法主要分为两个阶段:

第一个阶段是激励传播:每次迭代中的传播环节也分为两步:1.(前向传播阶段)将训练送入网络以获得激励响应。2.(反向传播阶段)将激励响应与训练输入对应的目标输出求差,从而获得隐层和输出层的响应误差。

第二个阶段是权重更新:对于每个突触上的权重,更新步骤也有两步(参见上篇文章当中对梯度下降算法的讲述):1.得到对应的梯度。2.用当前权重减去梯度。

深度学习基础_第10张图片

三层网络BP算法示例

BP算法实际上就是应用在多层网络中的梯度下降算法,原理与梯度下降算法相同,但区别在于BP算法需要求不同层连接所对应的梯度,而不是像普通的梯度下降算法那样,只需处理一层的问题。

利用BP算法计算输出层连接的梯度时,过程与普通梯度下降算法相同;但如果j是网络中任一内层神经元,求损失函数E对于相应连接权重wijij下一层的神经元,wij即两者之间连接的权重)的偏导数就不太容易了,需要先求对oj的偏导。 

考虑E为接受来自神经元j输入的所有神经元L = u,v,...,w输入的函数:

oj取全微分,可以得到该导数的一个递归表达式:

也即,只要知道所有下一层(指离输出层更近的一层)的输出ol的导数,即可计算oj的导数,把它们放在一起:

其中:

所以得到BP算法的权重迭代公式(与普通梯度下降法参数迭代公式形式类似):

以上即为BP算法推导的全过程。

BP算法说到底是种梯度下降算法,前面也提到过,梯度下降法能得到局部最优,但并不能保证一定会得到全局最优。我们通常采用RBM pre-train的方法来避免其收敛到局部最小值。

根据前面的内容,好像稀疏自动编码器(sparse autoencoder)堆叠得到栈式自动编码器(stacked autoencoders),RBM堆叠得到DBN;而且二者都可以被用来做有监督DNN的预训练,用的还都是同样的无监督逐层预训练方法,二者实际上也都是起到了特征探测器的作用,都是给定一个输入,得到一个中间层,并利用中间层去重构一个和输入相同的样本,然后利用不同的评价指标,通过某种优化方法,尽可能的缩小输出样本和输入样本之间的差异。那它们的区别在什么地方呢?

首先Autocoder是一个确定模型,它的输入和输出之间有着严格的数学公式;而RBM源于BM,源于玻尔兹曼分布,是一个基于概率的不确定模型。

Autocoder训练时采用BP算法,直接做梯度下降(看成只有一层的BP神经网络),而RBM采用CD-k算法,只能利用k次吉布斯采样的结果去近似的计算梯度。

深度神经网络的训练

一般对DNN的训练要从两个角度去考虑,第一个是如何让网络在训练集上有良好的表现,第二个是如何在训练集表现良好的前提下,使其在测试集上也有同样的表现。

如何在训练集上调优

选择合适的损失函数

前面我们默认采用的都是平方误差损失函数,但很多时候,平方误差损失函数并不是我们最好的选择,比如当我们用Softmax作为输出层时,就更倾向于选择交叉熵损失函数。

深度学习基础_第11张图片

交叉熵和平方误差损失函数曲面

前面我们也提到过熵的定义,知道熵是一个不确定性的测度,也就是说,我们对于某件事情知道得越多,那么,熵就越小,因而对于试验的结果我们越不感到意外。交叉熵的概念就是用来衡量估计模型与真实概率分布之间的差异情况的。

多输入单输出神经元交叉熵损失函数

其中y为期望的输出,a为神经元实际的输出(a=σ(z), where z=∑Wj*Xj+b)。

与方差误差函数一样,交叉熵函数同样拥有两个性质,一个是非负性,一个是当真实输出a与期望输出y接近时,损失函数的函数值接近于0。

另外,它可以克服方差代价函数更新权重过慢的问题。我们看看它的导数:

 

从式子中我们可以看到,权重的更新是受σ(z)−y这一项影响,也即误差越大,权重更新速度越快,误差越小,更新速度越慢。这项性质在上面的交叉熵损失函数曲面图中也可以体现出来,误差越大,曲面越陡峭,偏导也就越大,梯度下降也就越快。

Mini-batch

我们上篇文章《浅谈机器学习基础》中,讲过梯度下降算法(batch-GD),讲过随机梯度下降算法(SGD),它们的区别在于,batch-GD单次迭代要使用整个训练集,而SGD单次迭代每次只使用单个样本。那我们就一定要走两个极端吗,要么全部使用,要么只使用一个?我们可以选择只使用一部分,把整个训练集拆成一部分一部分使用,这就叫做mini-batch,我们可以把SGD看做mini-batch的特例,也即batch size = 1,而batch-GD的batch size就等于整个训练集。

而且还要引入一个epoch的概念,一次参数更新叫做一次迭代,当经历若干次迭代后,全部训练样本都已经被使用过了,这就叫一个epoch。batch-GD一次迭代就是一个epoch,SGD要迭代训练样本数目次,才算是一个epoch。

深度学习基础_第12张图片

各类梯度下降算法

对于batch-GD,每次迭代的梯度方向计算由所有训练样本共同投票决定,计算损失函数在整个训练集上的梯度方向,沿着该方向搜寻下一个迭代点。”batch“的含义是训练集中所有样本参与每一轮迭代。

batch GD每一轮迭代需要所有样本参与,对于大规模的机器学习应用,经常有billion级别的训练集,计算复杂度非常高。因此,有学者就提出,反正训练集只是数据分布的一个采样集合,我们能不能在每次迭代只利用部分训练集样本呢?这就是mini-batch算法。

假设训练集有m个样本,每个mini-batch(训练集的一个子集)有b个样本,那么,整个训练集可以分成m/b个mini-batch。

SGD就是mini-batch的一个特殊情况,batch size = 1。

然后是Online GD,随着互联网行业的蓬勃发展,数据变得越来越“廉价”。很多应用有实时的,不间断的训练数据产生。在线学习(Online Learning)算法就是充分利用实时数据的一个训练算法。

Online GD于mini-batch GD/SGD的区别在于,所有训练数据只用一次,然后丢弃。这样做的好处是可以最终模型的变化趋势。比如搜索广告的点击率(CTR)预估模型,网民的点击行为会随着时间改变。用batch算法(每天更新一次)一方面耗时较长(需要对所有历史数据重新训练);另一方面,无法及时反馈用户的点击行为迁移。而Online Leaning的算法可以实时的最终网民的点击行为迁移。

选择新的激活函数

这里要先提一个问题,就是神经网络并不一定是层数越多,越深越好,层数多了也会随之产生很多问题,比如梯度消失和梯度爆炸。

先简单的说一下梯度消失现象,因为前面也讲过BP算法,我们知道,梯度的传播是反向的,从输出层向输入层,如果层数过多,就会导致这样的问题,越靠近输出层的层梯度越大,学习的也越快,而越靠输入层,梯度就越小,参数更新也就越慢,如果整个网络的层数又多,会导致输入层附近的层几乎无法有效更新,梯度几乎为零,这就叫梯度消失。

但是梯度消失的本质是什么?我们前面讲过BP算法的推导:

其中:

可以看到,除了输出层,计算每一层的梯度都是要乘以上一层梯度的一部分以及层间连接的权重和的,而计算上一层的梯度这部分又要乘以上上层梯度的一部分,是个连乘式,所以层数越多,就是越多的数相乘,如果这些数字都小于1,那么乘的越多,越接近输入层,算出来的梯度就越接近零,如果这些数字都大于1,那么乘的越多,越接近输入层,算出来的梯度就越大。梯度接近零叫做梯度消失,梯度变得过大就叫做梯度爆炸,而且我们发现这个乘数是个累加项,而且这个累加项里面,包含权重wjl,所以如果初始权重过小,那梯度消失的风险就大,如果初始权重过大,那就很可能会梯度爆炸,唯一可能的情况是让这些乘积基本等于1,但这不太可能。

那我们怎么解决这个梯度消失的问题呢?看资料里面讲,从2006年起,我们通过前面讲过的RBM pre-train来解决梯度消失的问题,毕竟RBM pre-train靠的是无监督逐层训练,是种最大似然学习,最后的有监督BP,只是用来微调的。但是2015年之后,人们一般采用ReLU激活函数来避免梯度消失/爆炸的问题

Rectified Linear Unit (修正线性单元/线性整流函数,ReLU),函数图像如下:


深度学习基础_第13张图片

线性整流函数图像

我们将其与其他常见的Sigmoid激活函数图像作对比:


Sigmoid

Sigmoid

ReLU函数的表现通常优于其他激活函数,广泛使用于诸如图像识别等计算机视觉人工智能领域,其具有如下几个优点:

  • 计算速度快,因为其由两段线性函数构成,计算起来不知道比Sigmoid快到哪里去
  • ReLU有一定仿生物学原理,ReLU激活函数与人脑中神经元的激活方式最为类似,人脑接受相应刺激后,只有少量相关神经元(1%-4%)被激活,而大多数神经元都处于被抑制的状态,Sigmoid函数在输入为0时就已经是1/2半饱和的稳定状态了,不够符合实际生物学对人工神经网络的期望,而ReLU的表现要好的多,不过一般情况下,使用了ReLU,网络中也大概有50%的神经元会处于激活状态。
  • 采用ReLU可以解决梯度消失/爆炸的问题,前面讲过梯度消失/爆炸的原理,在于复杂多层网络下的梯度连乘,而ReLU的价值就在于抑制相当一部分神经元的激活,实际上是对网络进行了简化,去掉了网络中被抑制的那些神经元。

ReLU函数还有几种变体,往往是更改了输入小于0时的函数曲线,比如Leaky ReLU、Parametric ReLU等,不详述。

另外还要说的一点就是Maxout,ReLU其实是Maxout的一种特例。

那什么是Maxout?

 

深度学习基础_第14张图片

Maxout

我们知道,在人工神经网络中,规定神经元函数只能对输入变量线性组合后的结果进行一次非线性变换。而这次非线性变换,就是激活函数。

接下来具体讲一下Maxout的算法流程,首先对于每个隐藏层神经元,如果它接受d个输入,那么Maxout隐藏层每个神经元的计算公式如下:

上面的公式就是maxout隐藏层神经元i的计算公式。其中,k就是maxout层所需要的参数了,由我们人为设定大小。公式中Z的计算公式为:

权重W是一个大小为(d,m,k)三维矩阵,b是一个大小为(m,k)的二维矩阵,这两个就是我们需要学习的参数。而这个k就是我们同时训练的参数组数。本来传统的人工神经网络,第i层到第i+1层只有一组参数(k=1),但是现在,我们同时训练k组参数,然后选择激活值最大的作为输出。

以前的做法是,z=W*X+b,然后out=f(z)f就是我们通常讲的激活函数,比如Sigmoid、tanh。

而在Maxout里面,相当于在每个输出神经元前面又加了一层,相当于对输入变量线性组合后的结果并不直接送到输出神经元里面,而是相当于新加了一个『隐隐层』,这个『隐隐层』有k个神经元,这个k就是Maxout里面的那个参数k,然后前面线性组合的结果就分别送到这k个神经元里面,分别进行计算(比如k等于5):

z1=w1*x+b1
z2=w2*x+b2
z3=w3*x+b3
z4=w4*x+b4
z5=w5*x+b5

然后取最大的out=max(z1,z2,z3,z4,z5)作为输出,同时训练k组参数,这就是Maxout。

Maxout激活函数的图像如下:

深度学习基础_第15张图片

k=2和k=3时的Maxout示例

我们可以看到k=2时第一个图像就是ReLU的函数图像。按我的理解,ReLU就是Maxout的k=2,然后在隐隐层放了一个z=0的神经元。

自适应学习速率

上篇文章讲梯度下降时提到过学习速率η,它对训练效果也起到很重要的影响,如果η过大,那每次更新后,总误差可能并不会缩小;而如果η过小,那训练速度又会变得相当慢。所以我们很自然的有这样的想法,学习速率η不应该是一直不变的,我们希望这个学习速率η能够随着每次epoch而减小。

Adagrad就是针对这一问题提出的,自适应地为各个参数分配不同学习率的算法。其公式如下:

 

Adagrad

学习速率η不再恒定不变,而是根据上式持续更新,下面的分母会随着迭代次数的增加累加gigi是第i次更新所得到偏导数。

也即,对于所有的参数来讲,学习速率都是越来越小的。而且,偏导越小,学习速率减小的就越慢。

第一条很好理解,第二条要简单解释一下,如果偏导很小,说明本来的更新速率就很小,如果再将学习速率这个参数以一个较快的速度减小,那这个维度下的总参数更新速率就会变的过慢

当然Adagrad也不是唯一的算法,拥有类似功能的还有RMSprop、Adadelta、AdaSecant、Adam等,而且一般而言Adam是目前的最优选择。

Momentum

我们考虑这样一个问题,如果单纯的只靠梯度来作为权重更新的唯一依据,会出现什么样的问题,如下图所示:

深度学习基础_第16张图片

当梯度非常小,也即曲面在对应维度上非常平缓时,权重的更新会变得相当慢;在鞍点,也即偏导数为0的点,该维度权重会停止更新;而且也很容易停留在局部最小值而达不到全局最小值。

Momentum是冲量的意思,不过我们可以简单的把它理解为惯性,把梯度下降看做一个小球沿曲线滑落的过程,这样即便在梯度为零的点,也能以一个较快的速度进行梯度下降,甚至还有可能帮助损失函数突破局部最小值的限制,到达全局最小值。

前面所提到的表现优秀的Adam算法,就相当于RMSProp (高级版Adagrad) + Momentum

如何优化在测试集上的表现

模型由于采用了过于复杂的参数,从而在训练集上拥有良好表现,而在测试集上表现很差,这样的现象叫做过拟合。这一部分就是要讲如何解决过拟合的问题。

增大训练集

首先来讲最简单的一个方法,增大训练集,通过使用更大的训练集来增强模型对于各种样本的适应性。

增大训练集也有两种方法,一个自然是去找到更多的训练样本,而另一个,是去创造更多的训练样本。比如在图像识别中,我们可以通过对已有图像训练样本的角度进行调整来创造一个新的训练样本,我们也可以通过在训练样本中加上一些噪声来创造新的训练样本等。

提早停止(Early Stopping)

深度学习基础_第17张图片

Early Stopping

模型在测试集上的误差往往首先会随着测试集误差的减小而减小,但到了后期,模型就会倾向于通过过拟合来进一步降低自身在训练集上的误差,而这样的优化实际上是升高了模型在测试集上的误差的。所以我们可以通过提前停止训练来一定程度上避免过拟合。

正则化

正则化的目的是为了防止过拟合,但是正则化为什么可以防止过拟合?

正则化是在我们通常的损失函数后面加一个正则项,这个正则项实际上是一个对参数大小的惩罚项,那为什么正则项可以限制参数不能过大?

因为正则项里面通常包含参数,而我们的优化目的又是尽可能的缩小损失函数函数值,所以在优化的过程中,我们就会让参数尽可能的小。那为什么参数小了就可以防止过拟合?我读的资料里面写的都是参数越大,模型越复杂,越容易过拟合,那为什么参数大了模型就越复杂?

我们可以想一下,模型函数求导后的式子中是会保留有参数的,如果参数越大,也就意味着模型的导数越大,也就意味着模型曲线越不平滑,也就越容易通过各种扭曲去拟合噪声样本点,也即越容易发生过拟合

L0,L1,L2正则项是机器学习中常用的正则项:

L0:指非零参数的个数。前面讲过正则项的目的是为了惩罚参数过大,在这里也就是希望零参数越多越好,非零参数越少越好;优化损失函数正好是限制了正则项过大,也即限制了非零参数的个数过多。但使用L0正则项有个问题,就是难以优化,所以一般不用

L1:

采用L1正则项

L2:

采用L2正则项

对于使用了L1、L2正则项的损失函数来说,往极小值处优化自身函数值实际上就限制了正则项不能过大,也就限制了w不能过大,也即防止了过拟合。

L1会趋向于产生少量的特征,而其他的特征都是0,也即实现稀疏,只保留少量特征。而L2会选择更多的特征,这些特征都会接近于0L2正则项也叫权重衰减,是最常用的正则项,而且带L2的回归,就是岭回归,上篇文章说『岭回归就是在原来最小二乘法式子求逆之前先加上一个阶数与样本数相同的对角矩阵,也即加上一个正则项,使矩阵为奇异的风险大降低,损失了无偏性,来换取高的数值稳定性』,里面的这个正则项,就可以理解为L2正则项。

Dropout

Dropout也是防止过拟合的一种方法。基本原理很简单,就是训练时,每次更新参数之前,随机去掉网络中p%的神经元,也即更改了网络结构,让整个网络变得更简单。如果与前面的梯度下降结合起来,那就是每次使用训练集的一个新的mini-batch之前,都随机丢掉网络中p%的神经元,用剩下的神经元进行训练,进行参数更新。

然后到使用测试集的时候,使用完整的网络,但所有权重统一乘以(1-p)%。因为训练时只用部分神经元就生成了较为合适的输出z,如果使用了全部的神经元而权重仍然使用训练时的权重,那结果可能就会变成zn倍。

而且因为前面讲了是随机去掉网络中p%的神经元的,所以可能若干次训练的神经网络是会共享部分神经元的,当然也可能不共享,如果p较大的话。

如果非要讲原理的话,我借用我在其他资料里面看到的,当一群人组队做事情的时候,如果每个人都想着,我的队友会干活的,那什么事情都完成不了;如果每个人都认为,我的队友不行,还是得靠我自己,那么事情会做的好的多。

Network Structure

有些神经网络的结构天然就是能防止过拟合的,比如CNN,池化过程避免了过拟合

CNN、RNN和LSTM

卷积神经网络(Convolutional Neural Network,CNN)

1984年,日本学者福岛基于感受区域概念提出了神经认知机。神经认知机可以看作是卷积神经网络的第一个实现网络,也是感受区域概念在人工神经网络领域的首次应用。神经认知机将一个视觉模式分解成许多feature,然后进入分层递阶式相连的feature maps进行处理,这样就可以将视觉系统模型化,使其能够在物体有位移或轻微变形的时候,也能完成识别。

深度学习基础_第18张图片

卷积神经网络LeNet-5示例

我们以用于手写数字识别的LeNet-5为例来讲卷积神经网络。

卷积神经网络由卷积层(Convolutions Layer)、池化层(Pooling Layer)和全连接层构成。全连接层在最后,前面是若干卷积层和池化层,每个卷积层后面跟一个池化层,如此重复。

图中展示了LeNet-5网络的结构,一共七层,前面四层是卷积层和池化层(池化层又叫子采样层,也即Subsample Layer),后面三层是全连接层,最后一层输出层是高斯连接层,也是全连接层,共有10个节点,分别代表数字0到9,且如果节点i的值为0,则网络识别的结果是数字i。采用的是欧式径向基函数(ERBF)的网络连接方式。假设x是上一层的输入,y是ERBF的输出,则ERBF输出的计算方式是:

理解卷积神经网络的核心在于理解前面的卷积层和池化层。既然我们将卷积神经网络分为了卷积层、池化层和全连接层,则隐含了前面的卷积层和池化层并不是全连接的,那它们是怎么连接的呢?

介绍连接方式之前需要先介绍卷积层与池化层的性质:

卷积层:卷积层由若干张feature map(FM)构成。对输入数据应用卷积核(可以认为是对特定feature非常敏感的探测器),在输入数据上滚一遍我们的卷积核,就得到了一张FM,FM上记录了卷积核在原图不同区域的激活程度(与该卷积核的feature越契合,激活程度越高),也即去掉了读不懂的数据,留下了符合一定feature的数据。每个卷积核拥有一个feature,也就能产生一张对应feature的FM。

池化层:池化层的价值在于缩减输入数据的规模,FM上k*k一共k^2个激活值合并成为池化层上的一个激活值,合并的方法有很多种,比如最大值合并、平均值合并及随机合并,需要视情况而定,比如如果要确定『有没有』的问题,就要采用最大值合并,把最高的激活值保留下来。

然后最后一个池化层后面连接到一个或多个全连接层,全连接层的输出就是最后的输出。训练过程通过改进的反向传播实现,在反向传播的时候需要特别考虑到池化层合并激活值的方法,最大值合并、平均值合并等,均需要采用特定的处理方法,并以此来更新卷积核。

我们能人工定义的是卷积核的宽和高,还有卷积核的个数。卷积核对什么feature敏感,是先随机初始化,再经过BP算法慢慢训练出来的,卷积核的权重就是卷积神经网络主要需要学习的参数。

深度学习基础_第19张图片

3*3的一个卷积核

卷积神经网络通过『局部感知野』与『权值共享』大大减少了连接的个数,也即需要训练的参数的个数。

就拿原图像到第一层卷积层的连接举例,假设我们的图像是1000*1000的,则有10^6个隐层神经元,那么它们全连接的话,也就是每个隐层神经元都连接图像的每个像素点,就有10^12个连接,也即10^12个权值参数需要训练,这显然是不值得的。但是对于一个只识别特定feature的卷积核,需要大到覆盖整个图像的所有像素点吗?通常是不需要的,一个特定feature,尤其是第一层需要提取的feature,通常都相当基础,只占图像很小的一部分。所以我们设置一个较小的局部感受区域,比如10*10,也即每个神经元只需要和这10*10的局部图像相连接,所以10^6个神经元也就有10^8个连接。这就叫局部感知野。

那什么叫权值共享呢?在上面的局部连接中,10^6个神经元,每个神经元都对应100个参数,所以是10^8个参数,那如果每个神经元所对应的参数都是相同的,那需要训练的参数就只有100个了。

这后面隐含的道理在于,这100个参数就是一个卷积核,而卷积核是提取feature的方式,与其在图像上的位置无关,图像一个局部的统计特征与其他局部的统计特征是一样的,我们用在这个局部抽取feature的卷积核也可以用在图像上的其它任何地方。

而且这100个参数只是一种卷积核,只能提取一种feature,我们完全可以采用100个卷积核,提取100种feature,而所需要训练的参数也不过10^4,最开始我们训练10^12个参数,还只能提取一种特征。选取100个卷积核,我们就能得到100张FM,每张FM可以看做是一张图像的不同通道。

接下来我要具体介绍一下利用卷积核卷积生成FM的过程:

3*3卷积核在5*5图像上卷积的过程

左侧绿色的是5*5的原图,左侧黄色的是3*3的卷积核覆盖的区域,右侧是3*3的FM。

原图就不说了,卷积核的权重是黄色区域每个格子右下角乘号后面的数字,也即卷积核就是我们前面用作示例的那个卷积核:

深度学习基础_第20张图片

3*3的一个卷积核

具体的卷积过程,就是将卷积核覆盖在原图上,从左上角开始,一次向右移动一个像素,卷积完一行,整个卷积核向下移动一个像素,再开始卷积。在卷积核覆盖的区域范围内,原图与卷积核对应位置的像素分别做乘法,再全部加和。

至于FM为什么是3*3的,因为(5-3)/1 + 1 = 3。原图5*5,卷积核3*3,按这样的方法法卷积(卷积核卷积的滑动步长为1),得到的feature也就是3*3的。也即这一层隐层的神经元的个数是3*3,不过这只是一张FM,如果10张相同的FM,那神经元的个数就是10倍了。

如果定义了滑动步长为2,那就每次向右移动2个像素了,一行结束也是向下移动2个像素,当然FM大小的计算方法也要随之改变了,也即(5-3)/2 + 1 = 2,公式为(原图宽高-卷积核宽高)/滑动步长 + 1

这样基本的卷积过程就讲完了,接下来讲池化过程。

 

池化过程

池化过程看起来要简单的多,就是一个取局部平均值\最大值的过程(根据具体池化方法决定)。人们可以计算图像一个区域上的某个特定特征的平均值 (或最大值)。这些概要统计特征不仅具有低得多的维度 (相比使用所有提取得到的特征),同时还会改善结果(不容易过拟合)。

另外需要提的一点是,前面说10*10的卷积核需要训练的参数是100个,严格来讲是错误的,其实是101个,因为每个卷积核还有一个可训练偏置。

接下来以LeNet-5为例,从头捋一遍卷积神经网络的过程,重新放一遍LeNet-5的图:

深度学习基础_第21张图片

卷积神经网络LeNet-5示例

输入层是32*32像素的图片,比数据集中最大的的字符(最大体积是20*20像素的字符,位于28*28像素区域的中心)大很多。这样做的原因是能使潜在的特征比如边缘的端点、拐角能够出现在最高层次的卷积核的接收域的中心。

然后第一层C1,6个卷积核,所以也就6张FM,卷积核是5*5的,至于为什么每张FM是28*28的,(32-5)/1 + 1 = 28。那C1一共有多少个需要训练的参数呢?(5*5+1)*6 = 156个可训练参数,每个卷积核26个可训练参数,6个卷积核,也就是156个可训练参数。那C1与原图一共有多少个连接呢?(28*28)*6*26 = 122304个连接,28*28的FM,一共有6张,所以乘6,这6张FM里的每一个点,都是采用了6种卷积核的其中之一卷积出来的,不管是这6种卷积核里的哪种,都有26个参数,也即26个连接,所以要乘以26。当然每张FM里面的点用的是同样的卷积核,连接数公式简记为(FM宽高*FM宽高)*可训练参数

然后第二层S2,以2*2的范围去池化,我们也称其为一个2*2的池化核。6张28*28的FM被池化成了14*14的图,这个算法很简单,可以参考上面池化层的动图去理解。这里的每个池化核有两个可训练参数,一个负责与池化核里4个输入相加的和相乘,另一个作为可训练偏置加在乘积上,最后得到池化结果。6张FM,也对应6个池化核,每个池化核2个参数,也即12个可训练参数。那S2层与C1层有多少连接呢?(14*14)*6*5 = 5880个连接,这里池化核与卷积核不同,对于卷积核而言,26个可训练参数,也即26个连接;而池化只有2个可训练参数,但是如果池化核也只有2个连接,那那4个输入是从哪来的呢,所以这里2*2的池化核对应5个连接。然后6张图,每张14*14,每个点5个连接,所以得到5880个连接。

然后是C3层,C3层同样通过5*5的卷积核去卷积每张图14*14的S2,然后得到的每张FM就是10*10的,算法与C1时相同。它有16种不同的卷积核,所以C3层就对应了16张FM。这里有个比C1层复杂的多的问题,就是C1层只卷积1张图,而C3层要卷积6张图。那这16张FM是如何卷积前面S2层的6张图的呢?如下图:

深度学习基础_第22张图片

C3层卷积S2层对应关系图

0-5这6张FM卷积S2中的3张图,6-11这6张FM卷积S2中连续的4张图,12-14这3张FM卷积S2中不连续的4张图,15这张FM卷积所有的6张图。FM0卷积图012、FM6卷积图0123、FM12卷积图0134、FM15卷积图012345。

我们知道一张FM对应一个卷积核,那一个卷积核怎样同时卷积多张图呢?我们把多张图上同一位置的卷积结果相加,然后代入激活函数:

双曲正切激活函数

我们来想一下卷积多张图的意义在哪?我们知道,越往后的卷积核的feature就越高级越抽象,而这个高级feature往往是通过组合低级feature得到的,比如低级feature可能是折线,而高级feature就可能是一个轮子、一张人脸卷积多张图就是组合低级feature尝试生成高级feature的过程,这种不对称的组合连接的方式有利于提取多种组合特征

这里计算可训练参数和连接数也比C1层复杂得多,C3层一共(5*5*3+1)*6 + (5*5*4+1)*6 + (5*5*4+1)*3 + (5*5*6+1)*1 = 1516个训练参数,需要注意的是,之前的算法是(5*5+1)*卷积核数这里不再适用,因为每个卷积核不再只卷积一张图,5\*5后面要接着乘以卷积图的张图,因为之前只有1张,所以就省略了,这里每个卷积核都卷积多张图,所以不能省略,而且要分开计算,因为不同的卷积核卷积图的张数也分为不同的几种;至于连接数,代之前的公式,一共(10*10)*1516 = 151600个连接。

再后面是S4层,用16个2*2的池化核将16张10*10的FM池化成16张5*5的图,一共16\*2 = 32个可训练参数,一共(5*5)*16*5 = 2000个连接。

然后是C5层,我们看到S4层每张图就已经是5*5的了,而我们的卷积核也是5*5的,所以卷积完了就是一个点。这里用120个卷积核,生成120张FM,每张FM就一个点。每张FM都卷积S4层全部16张图,卷积多张图的方法也和C3层讲的一样。

再后面是F6层,F6层是全连接层,有84个单元,与C5层全连接,有10164个可训练参数。如同经典神经网络,F6层计算输入向量和权重限量之间的点积,再加上一个偏置。然后将其传递给Sigmoid函数产生单元i的一个状态。

输出层也是全连接层,前面提到过它的计算方式,这里重复一下,一共10个输出,10个单元,每个单元有84个输入,且如果节点i的值为0,则网络识别的结果是数字i。采用的是欧式径向基函数(ERBF)的网络连接方式。假设x是上一层的输入,y是ERBF的输出,则ERBF输出的计算方式是:

其意义是计算每个输入向量与参数向量之间的欧式距离,输入离参数向量越远,ERBF的输出值就越大,输出值越小,也即越匹配越契合。一个ERBF的输出可以被理解为衡量输入模式和ERBF相关联类的一个模型的匹配程度的惩罚项。

CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN特征检测层通过训练数据进行学习,在使用CNN时,避免了显式的特征抽取,而隐式地从训练数据中进行学习;再者,由于同一FM上的神经元权值相同,所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,避免了特征提取和分类过程中数据重建的复杂度。

递归神经网络(RNN)

递归神经网络(RNN),是两种人工神经网络的总称。一种是时间递归神经网络(recurrent neural network),另一种是结构递归神经网络(recursive neural network)。时间递归神经网络的神经元间连接构成有向图,而结构递归神经网络利用相似的神经网络结构递归构造更为复杂的深度网络。RNN一般指代时间递归神经网络,也叫循环神经网络。单纯递归神经网络因为无法处理随着递归,梯度爆炸或消失的问题,难以捕捉长期时间关联;而LSTM(长短期记忆神经网络,Long-Short Term Memory)可以很好地解决这个问题。

RNN的目的是用来处理序列数据,普通的前馈神经网络,是从输入层到隐层再到输出层,相邻层的节点之间是全连接的,然而一层内的节点之间却是没有连接的。这种普通的神经网络对很多问题是无能为力的,例如,你要预测句子中的下一个词是什么就一般要用到前面的词,因为词与词之间往往不是相互独立的。RNN之所以被称为循环神经网络,就是因为一个序列当前的输出不仅和当前的输入有关,还和过去的输出有关。RNN会对前面的输出进行记忆并用在当前的输出计算之中,同时意味着隐层内的节点也不再是无连接的。

举一个例子,填槽问题,有这样一句话,『I would like to arrive Taipei on November 2nd』。将这句话作为输入提供给机票预订系统,需要填的槽位有三个,一个是出发地,一个是目的地,另一个是到达时间,当然这句话只能填两个。

首先我们尝试用普通前馈神经网络来解决这个问题。比如有这样一个神经网络,它有两个输出神经元,分别对应三个槽,一个槽是出发地,一个槽是目的地,一个槽是到达时间;然后我们要训练这个神经网络,使其在接受『I would like to arrive Taipei on November 2nd』输入序列时,目的地槽位对应输出神经元的激活值在输入Taipei时达到最大,而到达时间槽位对应输出神经元的激活值在输入November 2nd时达到最大?

那我们考虑一下,如果将输入序列这样修改一下『I would like to leave Taipei on November 2nd』,我们还能把Taipei填到目的地槽位里面吗?难道我们要先检索一下句子里的是leave还是arrive?要是人家用其他的词呢?这就是人工学习而不是机器学习了,都是治标不治本的做法。最本质的解决方法是要让神经网络拥有『记忆』。

深度学习基础_第23张图片

我们不断重复使用同样的网络结构,将其隐层相连,前面隐层的输出作为后面隐层输入的一部分使用。

上图是神经单元的展开,如果收起,则结构如下:

 

一个循环的神经单元

那使用RNN如何解决前面提到的问题呢?在RNN里,当前面的词不同时,对应的隐层输出也就不同,前面词的隐层输出作为输入的一部分提供给了Taipei对应的隐层,进而使得Taipei被填进每个槽位的概率也不同。从而实现,当前面是arrive时,将Taipei填进目的地槽;当前面是leave时,将Taipei填进出发地槽。

下面来讲RNN中广泛使用且效果极为出色的一种类型 —— LSTM(长短期记忆神经网络,Long-Short Term Memory)。

前面讲,普通RNN无法处理随着递归,梯度爆炸或消失的问题,这样导致普通RNN无法捕捉过长时间的关联。前面隐层输出的不同会随着梯度消失,距离越远,影响就越小。而LSTM通过特殊的结构解决了这个长期依赖的问题。

LSTM的结构这部分我主要读了两篇资料,一篇是Christopher Olah 的博文,另一篇是李宏毅教授Deep Learning Tutorial里面的对应内容。

这两篇资料的讲解,一篇以等价的逻辑结构来讲,更通俗;一篇以真实结构来讲,更深入,这里我准备加上自己的理解,将两种结构对比起来讲。

先说标准RNN的结构,所有的RNN都有神经网络的重复模块组成的链式结构。对于标准的RNN,这种重复模块有一个非常简单的结构,如一个单一的tanh(双曲正切)层:

 

深度学习基础_第24张图片

LSTM中也有这样的链式结构,但重复模块却具有和一般RNN不同的结构。前面标准RNN只有一个交互层,而LSTM有四个。

为了便于理解,我们先以LSTM的等价逻辑结构进行讲解:

 

深度学习基础_第25张图片

LSTM的等价逻辑结构

如图所示,LSTM的神经元由四部分组成,分别是:输入门、输出门、遗忘门和记忆细胞。接受4个输入,1个输出。输入门、输出门、遗忘门各接受一种控制信号输入。输入门还额外接受上个神经元的输入,输出门额外给出一个到下个神经元的输出。3种门是用来保护和控制细胞状态的。

下图展示了逻辑结构下的实际计算过程:

 

深度学习基础_第26张图片

首先,前面讲输入门、输出门、遗忘门各接受一种控制信号输入,也就是这里图上的zizozf,这三种信号进来要经过的函数f为激活函数,通常使用Sigmoid函数,我们知道Sigmoid函数的输出在0到1之间,非常适合作为门的控制信号,0代表完全舍弃(关闭),1代表完全保留(开启)。

关注图中门的开启关闭是如何起作用的,我们可以发现,假如输入门接受信号zi过小,导致对应Sigmoid函数的输出为0,则意味着输入门关闭,我们可以看到f(zi)与神经元的输入z处理得到的g(z)是相乘的关系,也即如果输入门关闭,则该LSTM神经元不再接收输入门的输入z。同理,如果输出门关闭,则该LSTM神经元输出门无法产生有效的输出a。而对于遗忘门,根据图中的公式可知,如果遗忘门关闭,则意味着记忆细胞过去的记忆值c将被忘记,该LSTM神经元的输出完全独立,不受过去输出的影响。(如果将遗忘门叫做记忆门或许更好理解,记忆门关闭则完全遗忘。)

LSTM计算过程举例:

 

深度学习基础_第27张图片

LSTM计算过程举例

左边的图,遗忘门那,c' = 3+cc是7,c'就得到10了。

理解了LSTM的逻辑结构,接下来我们看一下LSTM的真实结构,可以翻上去和标准RNN的结构图比较一下:

 

深度学习基础_第28张图片

LSTM的真实结构

我们先来解释一下图中的各种图标的含义:

 

深度学习基础_第29张图片

黄色方块代表一个神经网络层,里面的σ代表Sigmoid激活函数,tanh代表双曲正切激活函数。粉色的圈代表一次操作,比如求积求和。每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。

我们这里准备一部分一部分的将真实结构对应到前面的逻辑结构上去。先是逻辑结构中的记忆细胞:

 

深度学习基础_第30张图片

这里图中的Ct-1Ct的过程,就是前面逻辑结构中cc'的过程,前面讲cc'的过程有两部分,一部分是由遗忘门f(zf)决定前面的c是否参与到c'的计算中来,对应到真实结构上也就是图中的ft,它决定了Ct-1会不会加到C中去;另一部分就是输入门的输入,在讲逻辑结构的过程中,我们知道,输入门的输入也由两部分构成,一部分是信号输入zi代入Sigmoid函数的结果f(zi)决定了是否接受输入z,另一部分就是处理输入z得到的g(z)了。对应到上面的图中,it就是f(zi),负责决定输入z要不要被采用,图中与it相乘的另一部分,就可以理解为g(x)了。

接下来是遗忘门和输入门,在上面已经讲过了:

 

深度学习基础_第31张图片

遗忘门

 

深度学习基础_第32张图片

输入门

上面说了,f(zf)就对应着ft,看遗忘门图中的式子,括号里面的自然就是zf了,前面说过f函数就是Sigmoid函数就是图中的σ;然后是输入门,前面说,f(zi)就是it,看输入门图中右侧的第一个式子,括号里面的自然就是zi了,下面的式子就是g(z),那对应起来g函数就是tanh了,z就是括号里面的内容。

然后是输出门:

 

深度学习基础_第33张图片

前面讲,输出门接受一个信号zo,经过处理得到f(zo);计算出的c',经过h函数处理,得到h(c'),然后乘起来得到aa = h(c')f(zo)(如果忘了可以往回翻一下逻辑结构图)。这对应关系就很明显了,zo是图中第一个式子括号里面的那一大堆,ot就是f(zo),计算出的c'就是图中的Ct,这个前面说过了,然后h函数还是tanh函数,然后乘起来得到的那个a就是ht。我觉得我讲的真是不能再清楚了:)

LSTM可以通过控制门的开闭天然避免梯度消失。因为前面提到过,梯度消失的原因在于连乘式的产生,计算每层的梯度都需要用到下一层的梯度,需要一直乘到输出层,而对于LSTM来说,输入和记忆是相加的,也就是在逻辑结构那说的:

 

这有个什么好处呢,就是只要遗忘门不关闭(即f(zf)不等于0),前面的输出c的影响就永远不会消失。



 

你可能感兴趣的:(深度学习)