浅谈深度学习基础(上)

0.266字数 12686阅读 11135

第二个Topic讲深度学习,承接前面的《浅谈机器学习基础》。

深度学习简介

前面也提到过,机器学习的本质就是寻找最优模型,比如讲语音识别,就是将一段语音通过若干模型精准的转化为对应的文字,图像识别转化为识别结果,围棋程序转化为下一步走子,智能对话系统转化为对用户的回答。

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

讲到人工神经网络就不得不先讲感知机,感知机是最简单的一种人工神经网络,是一种二元线性分类器。感知机抽象于生物神经细胞,神经细胞结构大致可分为:树突、突触、细胞体及轴突。单个神经细胞可被视为一种只有两种状态的机器——激动时为『是』,而未激动时为『否』。神经细胞的状态取决于从其它的神经细胞收到的输入信号量,及突触的强度(抑制或加强)。当信号量总和超过了某个阈值时,细胞体就会激动,产生电脉冲。电脉冲沿着轴突并通过突触传递到其它神经元。为了模拟神经细胞行为,与之对应的感知机基础概念被提出,如权重(突触)、偏置(阈值)及激活函数(细胞体)。


感知机

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

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

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

简单的前馈神经网络

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

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

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

那具体处理问题时到底选多少层?每一层多少个神经元?这个只能靠直觉和试错。

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

就拿我们刚才提到过的分类场景来谈,具体一些,手写数字识别场景,对于一个神经网络,我们给定其一组初始参数值,然后将手写数字以图片的形式输入,在输出层,我们有10个输出层神经元,每个神经元的输出分别代表了判定输入是数字0~9的概率,哪个神经元的输出值最大,也即该神经网络的判定结果是该神经元对应的数字。

但是,在初始参数条件,一般神经网络的输出结果并不完全正确,我们需要对其参数进行优化,要优化参数,首先要度量误差,误差来源于预测结果与实际结果的距离,比如对于手写数字识别,给定一张写着『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层的神经网络模型用于分类任务,网络结构如下:


栈式自编码器的训练

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

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


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

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


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

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


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

玻尔兹曼机

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


玻尔兹曼分布概率公式
玻尔兹曼分布概率公式

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

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

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

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

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

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

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


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

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算法的具体过程借用别人文章中的截图来描述:


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的训练过程如下:


然后是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.用当前权重减去梯度。

三层网络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作为输出层时,就更倾向于选择交叉熵损失函数。

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

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


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

其中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。

各类梯度下降算法

对于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),函数图像如下:


线性整流函数图像
线性整流函数图像

我们将其与其他常见的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?


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激活函数的图像如下:


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

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


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

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

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

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

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

增大训练集

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

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

提早停止(Early Stopping)

Early Stopping

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

正则化

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

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

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

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

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

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

L1:


采用L1正则项

L2:


采用L2正则项

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

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

Dropout

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

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

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

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

Network Structure

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

推荐阅读更多精彩内容