1. 深度神经网络超参
模型的参数:就是模型可以根据数据可以自动学习出的变量,应该就是参数。比如,深度学习的权重,偏差等
超参数:就是用来确定模型的一些参数,超参数不同,模型是不同的(这个模型不同的意思就是有微小的区别,比如假设都是CNN模型,如果层数不同,模型不一样,虽然都是CNN模型哈。),超参数一般就是根据经验确定的变量。在深度学习中,超参数有:学习速率、迭代次数,层数,每层神经元的个数等等
2. 神经网络超参数选择
深度学习模型通常由随机梯度下降算法进行训练。随机梯度下降算法有许多变形:例如 Adam、RMSProp、Adagrad 等等。这些算法都需要你设置学习率。学习率决定了在一个小批量(mini-batch)中权重在梯度方向要移动多远。
如果学习率很低,训练会变得更加可靠,但是优化会耗费较长的时间,因为朝向损失函数最小值的每个步长很小。
如果学习率很高,训练可能根本不会收敛,损失函数一直处于波动中,甚至会发散。权重的改变量可能非常大,使得优化越过最小值,使得损失函数变得更糟。
训练应当从相对较大的学习率开始。这是因为在开始时,初始的随机权重远离最优值。在训练过程中,学习率应当下降,以允许细粒度的权重更新。
参考: https://www.jiqixin.com/articles/2017-11-17-2
批次大小是每一次训练神经网络送入模型的样本数。在 合理的范围之内 ,越大的 batch size 使下降方向越准确,震荡越小,通常取值为[16,32,64,128]。
Batch_Size=全部数据集 缺点:
1) 随着数据集的海量增长和内存限制,一次性载入所有的数据进来变得越来越不可行。
2) 以 Rprop 的方式迭代,会由于各个 Batch 之间的采样差异性,各次梯度修正值相互抵消,无法修正。
Batch_Size = 1 缺点:
使用在线学习,每次修正方向以各自样本的梯度方向修正,横冲直撞各自为政,难以达到收敛。
在合理范围内,增大 Batch_Size 有何好处?
1) 内存利用率提高了,大矩阵乘法的并行化效率提高。
2) 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
3) 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。
盲目增大 Batch_Size 有何坏处?
1) 内存利用率提高了,但是内存容量可能撑不住了。
2) 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
3) Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。
参考: https://blog.csdn.net/juronghui/article/details/78612653
迭代次数是指整个训练集输入到神经网络进行训练的次数,当测试错误率和训练错误率相差较小,且测试准确率趋于稳定时(达到最优),可认为当前迭代次数合适;当测试错误率先变小后变大时则说明迭代次数过大了,需要减小迭代次数,否则容易出现过拟合。
用激活函数给神经网络加入一些非线性因素,使得网络可以更好地解决较为复杂的问题。参考: https://blog.csdn.net/tyhj_sf/article/details/79932893
它能够把输入的连续实值变换为0和1之间的输出。
缺点:
1) 在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。
2) Sigmoid 的 output 不是0均值,使得收敛缓慢。batch的输入能缓解这个问题。
它解决了Sigmoid函数的不是zero-centered输出问题,然而梯度消失的问题和幂运算的问题仍然存在。
tanh函数具有中心对称性,适合于有对称性的二分类
虽然简单,但却是近几年的重要成果,有以下几大优点:
1) 解决了梯度消散问题 (在正区间)
2)计算速度非常快,只需要判断输入是否大于0
3)收敛速度远快于sigmoid和tanh
ReLU也有几个需要特别注意的问题:
1)ReLU的输出不是zero-centered
2)Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
为了解决Dead ReLU Problem,提出了将ReLU的前半段设为 αx 而非 0 ,如 PReLU 。
1)深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出。所以要尽量选择输出具有zero-centered特点的激活函数以加快模型的收敛速度。
2)如果使用 ReLU,那么一定要小心设置 learning rate,而且要注意不要让网络出现很多 “dead” 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout.
3)最好不要用 sigmoid,你可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout.
公式: https://www.cnblogs.com/xiaobingqianrui/p/10756046.html
优化器比较: https://blog.csdn.net/weixin_40170902/article/details/80092628
3. 循环神经网络(RNN)浅析
RNN是两种神经网络模型的缩写,一种是递归神经网络(Recursive Neural Network),一种是循环神经网络(Recurrent Neural Network)。虽然这两种神经网络有着千丝万缕的联系,但是本文主要讨论的是第二种神经网络模型——循环神经网络(Recurrent Neural Network)。
循环神经网络是指一个随着时间的推移,重复发生的结构。在自然语言处理(NLP),语音图像等多个领域均有非常广泛的应用。RNN网络和其他网络最大的不同就在于RNN能够实现某种“记忆功能”,是进行时间序列分析时最好的选择。如同人类能够凭借自己过往的记忆更好地认识这个世界一样。RNN也实现了类似于人脑的这一机制,对所处理过的信息留存有一定的记忆,而不像其他类型的神经网络并不能对处理过的信息留存记忆。
循环神经网络的原理并不十分复杂,本节主要从原理上分析RNN的结构和功能,不涉及RNN的数学推导和证明,整个网络只有简单的输入输出和网络状态参数。一个典型的RNN神经网络如图所示:
由上图可以看出:一个典型的RNN网络包含一个输入x,一个输出h和一个神经网络单元A。和普通的神经网络不同的是,RNN网络的神经网络单元A不仅仅与输入和输出存在联系,其与自身也存在一个回路。这种网络结构就揭示了RNN的实质:上一个时刻的网络状态信息将会作用于下一个时刻的网络状态。如果上图的网络结构仍不够清晰,RNN网络还能够以时间序列展开成如下形式:
等号右边是RNN的展开形式。由于RNN一般用来处理序列信息,因此下文说明时都以时间序列来举例,解释。等号右边的等价RNN网络中最初始的输入是x0,输出是h0,这代表着0时刻RNN网络的输入为x0,输出为h0,网络神经元在0时刻的状态保存在A中。当下一个时刻1到来时,此时网络神经元的状态不仅仅由1时刻的输入x1决定,也由0时刻的神经元状态决定。以后的情况都以此类推,直到时间序列的末尾t时刻。
上面的过程可以用一个简单的例子来论证:假设现在有一句话“I want to play basketball”,由于自然语言本身就是一个时间序列,较早的语言会与较后的语言存在某种联系,例如刚才的句子中“play”这个动词意味着后面一定会有一个名词,而这个名词具体是什么可能需要更遥远的语境来决定,因此一句话也可以作为RNN的输入。回到刚才的那句话,这句话中的5个单词是以时序出现的,我们现在将这五个单词编码后依次输入到RNN中。首先是单词“I”,它作为时序上第一个出现的单词被用作x0输入,拥有一个h0输出,并且改变了初始神经元A的状态。单词“want”作为时序上第二个出现的单词作为x1输入,这时RNN的输出和神经元状态将不仅仅由x1决定,也将由上一时刻的神经元状态或者说上一时刻的输入x0决定。之后的情况以此类推,直到上述句子输入到最后一个单词“basketball”。
接下来我们需要关注RNN的神经元结构:
上图依然是一个RNN神经网络的时序展开模型,中间t时刻的网络模型揭示了RNN的结构。可以看到,原始的RNN网络的内部结构非常简单。神经元A在t时刻的状态仅仅是t-1时刻神经元状态与t时刻网络输入的双曲正切函数的值,这个值不仅仅作为该时刻网络的输出,也作为该时刻网络的状态被传入到下一个时刻的网络状态中,这个过程叫做RNN的正向传播(forward propagation)。注:双曲正切函数的解析式如下:
双曲正切函数的求导如下:
双曲正切函数的图像如下所示:
这里就带来一个问题:为什么RNN网络的激活函数要选用双曲正切而不是sigmod呢?(RNN的激活函数除了双曲正切,RELU函数也用的非常多)原因在于RNN网络在求解时涉及时间序列上的大量求导运算,使用sigmod函数容易出现梯度消失,且sigmod的导数形式较为复杂。事实上,即使使用双曲正切函数,传统的RNN网络依然存在梯度消失问题,无法“记忆”长时间序列上的信息,这个bug直到LSTM上引入了单元状态后才算较好地解决。
这一节主要介绍与RNN相关的数学推导,由于RNN是一个时序模型,因此其求解过程可能和一般的神经网络不太相同。首先需要介绍一下RNN完整的结构图,上一节给出的RNN结构图省去了很多内部参数,仅仅作为一个概念模型给出。
上图表明了RNN网络的完整拓扑结构,从图中我们可以看到RNN网络中的参数情况。在这里我们只分析t时刻网络的行为与数学推导。t时刻网络迎来一个输入xt,网络此时刻的神经元状态st用如下式子表达:
t时刻的网络状态st不仅仅要输入到下一个时刻t+1的网络状态中去,还要作为该时刻的网络输出。当然,st不能直接输出,在输出之前还要再乘上一个系数V,而且为了误差逆传播时的方便通常还要对输出进行归一化处理,也就是对输出进行softmax化。因此,t时刻网络的输出ot表达为如下形式:
为了表达方便,笔者将上述两个公式做如下变换:
以上,就是RNN网络的数学表达了,接下来我们需要求解这个模型。在论述具体解法之前首先需要明确两个问题:优化目标函数是什么?待优化的量是什么?
只有在明确了这两个问题之后才能对模型进行具体的推导和求解。关于第一个问题,笔者选取模型的损失函数作为优化目标;关于第二个问题,我们从RNN的结构图中不难发现:只要我们得到了模型的U,V,W这三个参数就能完全确定模型的状态。因此该优化问题的优化变量就是RNN的这三个参数。顺便说一句,RNN模型的U,V,W三个参数是全局共享的,也就是说不同时刻的模型参数是完全一致的,这个特性使RNN得参数变得稍微少了一些。
不做过多的讨论,RNN的损失函数选用交叉熵(Cross Entropy),这是机器学习中使用最广泛的损失函数之一了,其通常的表达式如下所示:
上面式子是交叉熵的标量形式,y_i是真实的标签值,y_i*是模型给出的预测值,最外面之所以有一个累加符号是因为模型输出的一般都是一个多维的向量,只有把n维损失都加和才能得到真实的损失值。交叉熵在应用于RNN时需要做一些改变:首先,RNN的输出是向量形式,没有必要将所有维度都加在一起,直接把损失值用向量表达就可以了;其次,由于RNN模型处理的是序列问题,因此其模型损失不能只是一个时刻的损失,应该包含全部N个时刻的损失。
故RNN模型在t时刻的损失函数写成如下形式:
全部N个时刻的损失函数(全局损失)表达为如下形式:
需要说明的是:yt是t时刻输入的真实标签值,ot为模型的预测值,N代表全部N个时刻。下文中为了书写方便,将Loss简记为L。在结束本小节之前,最后补充一个softmax函数的求导公式:
由于RNN模型与时间序列有关,因此不能直接使用BP(back propagation)算法。针对RNN问题的特殊情况,提出了BPTT算法。BPTT的全称是“随时间变化的反向传播算法”(back propagation through time)。这个方法的基础仍然是常规的链式求导法则,接下来开始具体推导。虽然RNN的全局损失是与全部N个时刻有关的,但为了简单笔者在推导时只关注t时刻的损失函数。
首先求出t时刻下损失函数关于o_t*的微分:
求出损失函数关于参数V的微分:
因此,全局损失关于参数V的微分为:
求出t时刻的损失函数关于关于st*的微分:
求出t时刻的损失函数关于s_t-1*的微分:
求出t时刻损失函数关于参数U的偏微分。注意:由于是时间序列模型,因此t时刻关于U的微分与前t-1个时刻都有关,在具体计算时可以限定最远回溯到前n个时刻,但在推导时需要将前t-1个时刻全部带入:
因此,全局损失关于U的偏微分为:
求t时刻损失函数关于参数W的偏微分,和上面相同的道理,在这里仍然要计算全部前t-1时刻的情况:
因此,全局损失关于参数W的微分结果为:
至此,全局损失函数关于三个主要参数的微分都已经得到了。整理如下:
接下来进一步化简上述微分表达式,化简的主要方向为t时刻的损失函数关于ot的微分以及关于st*的微分。已知t时刻损失函数的表达式,求关于ot的微分:
softmax函数求导:
因此:
又因为:
且:
有了上面的数学推导,我们可以得到全局损失关于U,V,W三个参数的梯度公式:
由于参数U和W的微分公式不仅仅与t时刻有关,还与前面的t-1个时刻都有关,因此无法写出直接的计算公式。不过上面已经给出了t时刻的损失函数关于s_t-1的微分递推公式,想来求解这个式子也是十分简单的,在这里就不赘述了。
以上就是关于BPTT算法的全部数学推导。从最终结果可以看出三个公式的偏微分结果非常简单,在具体的优化过程中可以直接带入进行计算。对于这种优化问题来说,最常用的方法就是梯度下降法。针对本文涉及的RNN问题,可以构造出三个参数的梯度更新公式:
依靠上述梯度更新公式就能够迭代求解三个参数,直到三个参数的值发生收敛。
这是笔者第一次尝试推导RNN的数学模型,在推导过程中遇到了非常多的bug。非常感谢互联网上的一些公开资料和博客,给了我非常大的帮助和指引。接下来笔者将尝试实现一个单隐层的RNN模型用于实现一个语义预测模型。
4. 循环神经网络
花书中关于RNN的内容记录于 https://www.jianshu.com/p/206090600f13 。
在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。在生物神经网络中,神经元之间的连接关系要复杂的多。 前馈神经网络可以看作是一个复杂的函数,每次输入都是独立的,即网络的输出只依赖于当前的输入。但是在很多现实任务中,网络的输入不仅和当前时刻的输入相关,也和其过去一段时间的输出相关 。因此,前馈网络难以处理时序数据,比如视频、语音、文本等。时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变。因此,当处理这一类和时序相关的问题时,就需要一种能力更强的模型。
循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络。在循环神经网络中,神经元不但可以接受其它神经元的信息,也可以接受自身的信息,形成具有环路的网络结构。 和前馈神经网络相比,循环神经网络更加符合生物神经网络的结构。循环神经网络已经被广泛应用在语音识别、语言模型以及自然语言生成等任务上。循环神经网络的参数学习可以通过 随时间反向传播算法 来学习。
为了处理这些时序数据并利用其历史信息,我们需要让网络具有短期记忆能力。而前馈网络是一个静态网络,不具备这种记忆能力。
一种简单的利用历史信息的方法是建立一个额外的延时单元,用来存储网络的历史信息(可以包括输入、输出、隐状态等)。比较有代表性的模型是延时神经网络。
延时神经网络是在前馈网络中的非输出层都添加一个延时器,记录最近几次神经元的输出。在第 个时刻,第 层神经元和第 层神经元的最近 次输出相关,即:
延时神经网络在时间维度上共享权值,以降低参数数量。因此对于序列输入来讲,延时神经网络就相当于卷积神经网络 。
自回归模型(Autoregressive Model,AR) 是统计学上常用的一类时间序列模型,用一个变量 的历史信息来预测自己:
其中 为超参数, 为参数, 为第 个时刻的噪声,方差 和时间无关。
有外部输入的非线性自回归模型(Nonlinear Autoregressive with ExogenousInputs Model,NARX) 是自回归模型的扩展,在每个时刻 都有一个外部输入 ,产生一个输出 。NARX通过一个延时器记录最近几次的外部输入和输出,第 个时刻的输出 为:
其中 表示非线性函数,可以是一个前馈网络, 和 为超参数。
循环神经网络通过使用带自反馈的神经元,能够处理任意长度的时序数据。
给定一个输入序列 ,循环神经网络通过下面
公式更新带反馈边的隐藏层的活性值 :
其中 , 为一个非线性函数,也可以是一个前馈网络。
从数学上讲,上式可以看成一个动力系统。动力系统(Dynamical System)是一个数学上的概念,指 系统状态按照一定的规律随时间变化的系统 。具体地讲,动力系统是使用一个函数来描述一个给定空间(如某个物理系统的状态空间)中所有点随时间的变化情况。因此, 隐藏层的活性值 在很多文献上也称为状态(State)或隐状态(Hidden States) 。理论上,循环神经网络可以近似任意的非线性动力系统。
简单循环网络(Simple Recurrent Network,SRN)是一个非常简单的循环神经网络,只有一个隐藏层的神经网络。
在一个两层的前馈神经网络中,连接存在相邻的层与层之间,隐藏层的节点之间是无连接的。而 简单循环网络增加了从隐藏层到隐藏层的反馈连接 。
假设在时刻 时,网络的输入为 ,隐藏层状态(即隐藏层神经元活性值) 不仅和当前时刻的输入 相关,也和上一个时刻的隐藏层状态 相关:
其中 为隐藏层的净输入, 是非线性激活函数,通常为Logistic函数或Tanh函数, 为状态-状态权重矩阵, 为状态-输入权重矩阵, 为偏置。上面两式也经常直接写为:
如果我们把每个时刻的状态都看作是前馈神经网络的一层的话,循环神经网络可以看作是在时间维度上权值共享的神经网络 。下图给出了按时间展开的循环神经网络。
由于循环神经网络具有短期记忆能力,相当于存储装置,因此其计算能力十分强大。 前馈神经网络可以模拟任何连续函数,而循环神经网络可以模拟任何程序。
定义一个完全连接的循环神经网络,其输入为 ,输出为 :
其中 为隐状态, 为非线性激活函数, 和 为网络参数。
这样一个完全连接的循环神经网络可以近似解决所有的可计算问题 。
循环神经网络可以应用到很多不同类型的机器学习任务。根据这些任务的特点可以分为以下几种模式: 序列到类别模式、同步的序列到序列模式、异步的序列到序列模式 。
序列到类别模式主要用于序列数据的分类问题:输入为序列,输出为类别。比如在文本分类中,输入数据为单词的序列,输出为该文本的类别。
假设一个样本 为一个长度为 的序列,输出为一个类别 。我们可以将样本 按不同时刻输入到循环神经网络中,并得到不同时刻的隐藏状态 。我们可以将 看作整个序列的最终表示(或特征),并输入给分类器 进行分类:
其中 可以是简单的线性分类器(比如Logistic 回归)或复杂的分类器(比如多层前馈神经网络)
除了将最后时刻的状态作为序列表示之外,我们还可以对整个序列的所有状态进行平均,并用这个平均状态来作为整个序列的表示:
同步的序列到序列模式 主要用于序列标注(Sequence Labeling)任务,即每一时刻都有输入和输出,输入序列和输出序列的长度相同 。比如词性标注(Partof-Speech Tagging)中,每一个单词都需要标注其对应的词性标签。
输入为序列 ,输出为序列 。样本 按不同时刻输入到循环神经网络中,并得到不同时刻的隐状态 。每个时刻的隐状态 代表当前和历史的信息,并输入给分类器 得到当前时刻的标签 。
异步的序列到序列模式也称为 编码器-解码器(Encoder-Decoder)模型,即输入序列和输出序列不需要有严格的对应关系,也不需要保持相同的长度。 比如在机器翻译中,输入为源语言的单词序列,输出为目标语言的单词序列。
在异步的序列到序列模式中,输入为长度为 的序列 ,输出为长度为 的序列 。经常通过 先编码后解码 的方式来实现。先将样本 按不同时刻输入到一个循环神经网络(编码器)中,并得到其编码 。然后再使用另一个循环神经网络(解码器)中,得到输出序列 。为了建立输出序列之间的依赖关系,在解码器中通常使用非线性的自回归模型。
其中 分别为用作编码器和解码器的循环神经网络, 为分类器, 为预测输出 的向量表示。
循环神经网络的参数可以通过梯度下降方法来进行学习。给定一个训练样本 ,其中 为长度是 的输入序列, 是长度为 的标签序列。即在每个时刻 ,都有一个监督信息 ,我们定义时刻 的损失函数为:
其中 为第 时刻的输出, 为可微分的损失函数,比如交叉熵。那么整个序列上损失函数为:
整个序列的损失函数 关于参数 的梯度为:
即每个时刻损失 对参数 的偏导数之和。
循环神经网络中存在一个递归调用的函数 ,因此其计算参数梯度的方式和前馈神经网络不太相同。在循环神经网络中主要有两种计算梯度的方式: 随时间反向传播(BPTT)和实时循环学习(RTRL)算法。
随时间反向传播(Backpropagation Through Time,BPTT) 算法的主要思想是通过类似前馈神经网络的错误反向传播算法来进行计算梯度。
BPTT算法将循环神经网络看作是一个展开的多层前馈网络,其中“每一层”对应循环网络中的“每个时刻”。在“展开”的前馈网络中,所有层的参数是共享的,因此参数的真实梯度是将所有“展开层”的参数梯度之和 。
因为参数 和隐藏层在每个时刻 的净输入 有关,因此第 时刻的损失函数 关于参数 的梯度为:
其中 表示“直接”偏导数,即公式 中保持 不变,对 求偏导数,得到:
其中 为第 时刻隐状态的第 维; 除了第 个值为 外,其余都为 的行向量。
定义误差项 为第 时刻的损失对第 时刻隐藏神经层的净输入 的导数,则:
从而:
写成矩阵形式为:
由此得到整个序列的损失函数 关于参数 的梯度:
同理可得, 关于权重 和偏置 的梯度为:
在BPTT算法中,参数的梯度需要在一个完整的“前向”计算和“反向”计算后才能得到并进行参数更新。如下图所示。
与反向传播的BPTT算法不同的是,实时循环学习(Real-Time Recurrent Learning)是通过前向传播的方式来计算梯度。
假设循环神经网络中第 时刻的状态 为:
其关于参数 的偏导数为:
RTRL算法从第1 个时刻开始,除了计算循环神经网络的隐状态之外,还依次前向计算偏导数 。
两种学习算法比较:
RTRL算法和BPTT算法都是基于梯度下降的算法,分别通过前向模式和反向模式应用链式法则来计算梯度。 在循环神经网络中,一般网络输出维度远低于输入维度,因此BPTT算法的计算量会更小,但BPTT算法需要保存所有时刻的中间梯度,空间复杂度较高。RTRL算法不需要梯度回传,因此非常适合于需要在线学习或无限序列的任务中 。
循环神经网络在学习过程中的主要问题是由于 梯度消失或爆炸问题 ,很难建模长时间间隔(Long Range)的状态之间的依赖关系。
在BPTT算法中,我们有:
如果定义 ,则:
若 ,当 时, ,会造成系统不稳定,称为梯度爆炸问题;相反,若 ,当 时, ,会出现和深度前馈神经网络类似的梯度消失问题。
虽然简单循环网络理论上可以建立长时间间隔的状态之间的依赖关系,但是由于梯度爆炸或消失问题,实际上只能学习到短期的依赖关系。这样,如果t时刻的输出 依赖于 时刻的输入 ,当间隔 比较大时,简单神经网络很难建模这种长距离的依赖关系,称为 长程依赖问题(Long-Term dependencies Problem) 。
一般而言,循环网络的梯度爆炸问题比较容易解决,一般 通过权重衰减或梯度截断来避免。 权重衰减是通过给参数增加 或 范数的正则化项来限制参数的取值范围,从而使得 。梯度截断是另一种有效的启发式方法,当梯度的模大于一定阈值时,就将它截断成为一个较小的数。
梯度消失是循环网络的主要问题。除了使用一些优化技巧外,更有效的方式就是改变模型,比如让 ,同时使用 ,即:
其中 是一个非线性函数, 为参数。
上式中, 和 之间为线性依赖关系,且权重系数为1,这样就不存在梯度爆炸或消失问题。但是,这种改变也丢失了神经元在反馈边上的非线性激活的性质,因此也降低了模型的表示能力。
为了避免这个缺点,我们可以采用一种更加有效的改进策略:
这样 和 之间为既有线性关系,也有非线性关系,并且可以缓解梯度消失问题。但这种改进依然存在两个问题:
为了解决这两个问题,可以通过引入 门控机制 来进一步改进模型。
为了改善循环神经网络的长程依赖问题,一种非常好的解决方案是引入门控机制来控制信息的累积速度,包括 有选择地加入新的信息,并有选择地遗忘之前累积的信息 。这一类网络可以称为基于门控的循环神经网络(Gated RNN)。本节中,主要介绍两种基于门控的循环神经网络: 长短期记忆网络和门控循环单元网络。
长短期记忆(Long Short-Term Memory,LSTM)网络 是循环神经网络的一个变体,可以有效地解决简单循环神经网络的梯度爆炸或消失问题。
在 基础上,LSTM网络主要改进在以下两个方面:
其中 和 三个门(gate)来控制信息传递的路径; 为向量元素乘积; 为上一时刻的记忆单元; 是通过非线性函数得到的候选状态:
在每个时刻 ,LSTM网络的内部状态 记录了到当前时刻为止的历史信息。
在数字电路中,门(Gate)为一个二值变量{0, 1},0代表关闭状态,不许任何信息通过;1代表开放状态,允许所有信息通过。LSTM网络中的“门”是一种“软”门,取值在(0, 1) 之间,表示 以一定的比例运行信息通过 。LSTM网络中三个门的作用为:
(1)遗忘门 控制上一个时刻的内部状态 需要遗忘多少信息。
(2)输入门 控制当前时刻的候选状态 有多少信息需要保存。
(3)输出门
5. 神经网络结构搜索(Neural Architecture search)
神经网络搜索是生成和优化网络结构的有效工具 Neural Architecture Search 。
在不确定网络的长度和结构的情况下,使用一个循环神经网络(recurrent network)作为控制器来生成网络结构的字段,用来构建子神经网络。将训练子网络之后的准确率作为控制器回馈信号(reward signal),通过计算策略梯度(policy gradient)更新控制器,这样不断的迭代循环。在下一次迭代中,控制器将有更高的概率提出一个高准确率的网络结构。总之,伴随着时间的推移,控制器将通过不断的学习来提高搜索结果。如下图所示就是网络结构搜索。
神经结构搜索中,我们使用控制器产生神经网络的超参数。控制器使用的是一个循环神经网络。假设我们希望预测只有卷积层的前馈神经网络,就可以使用控制器来生成这些超参数的序列。
控制器可以看到代理(agent),生成的超参数序列(网络结构的描述字符串)可以被看做代理一系列的动作(actions) 。子网络在收敛后将达到准确率 。随后,将 作为回馈信号并使用增强学习训练控制器。具体的说,为了优化的结构,需要让控制器最大化期望回馈,期望回馈可以表示为 :
由于 不可微分,因此不能使用传统的BP算法。我们需要使用回馈更新代理的策略参数 ,进而实现回馈的最优化。这里我们使用 Williams 提出的REINFORCE,这个公式关联了回馈 和策略参数 :
上述数值的可以近似表示为:
是控制器一个批样本网络模型的数量, 是控制器生成的网络结构的超参数数量。 是第 个神经网络模型的准确率。
上述更新的梯度是梯度的无偏估计,但是方差很大。为了减小方差,我们使用了一个基线函数: 。
只要 不依赖与当前的动作,这个梯度导数将始终是无偏估计。这里,我们的 是准确率的指数移动平均值 EMA 。
在神经网络搜索中,训练一个子网络可能需要几个小时的时间。使用分布式训练和并行参数更新可以加速控制器的学习过程。我们使用参数服务器保存所有参数,服务器将参数分发给控制器,控制器被分成 个,每一个控制器使用得到的参数进行模型的构建,由于得到的参数可能不同,构建模型的策略也是随机的,导致每次构建的网络结构也会不同。每个控制器会构建一个batch, 个子网络,然后并行训练子网络得到准确率。计算出参数的梯度。然后计算完梯度的控制器将梯度传递到参数服务器,分别对自己负责的参数进行更新。接下来控制器得到更新的参数开始构建新的神经网络模型。这里,每一个控制器独立的发送自己的梯度更新服务器参数,不需要控制器之间同步,这及时异步更新。这里子网络的训练次数固定(epochs)。这种并行架构如下图所示
为了让控制器产生跳跃连接。在第 层中,添加一个锚点(anchor point)表示是否和前面的网络层连接:
表示控制器第 层网络锚点的隐藏状态, 介于0到 之间。根据这些sigmoids的结果来决定哪些网络层被用作当前层的输入。 , 和 是可训练参数。[图片上传失败...(image-feb8fe-1558488967580)]
为了产生循环元胞。控制器需要找到一个公式,以 和 作为输入, 作为结果。最简单的方式 ,这是一个基本的循环细胞的公式。一个更复杂的公式是广泛应用的LSTM循环元胞。
基础RNN和LSTM都可以描述为一个树形结构,输入 和 ,产生 ,这些变量作为叶子。控制器RNN需要标明树上的每个节点的结合方法(相加,按元素相乘等)和激活函数,用于融合两个输入并产生一个输出。然后两个节点输出又被作为树上下一个节点的输入。为了控制器可以选择这些方法和函数,我们将树上的节点以一定的顺序编号,这样控制器可以顺序的预测。
6. 循环神经网络
为什么卷积神经网络不会出现严重的数值问题呢?
卷积神经网络中每一层的权重矩阵 W 是不同的,并且在初始化时它们是独立同分布的,因此可以相互抵消,在多层之后一般不会出现严重的数值问题。
循环神经网络采用 ReLu 激活函数,只有当 W 的取值在单位矩阵附近时才能取得比较好的效果,因此需要将 W 初始化为单位矩阵。
Seq2Seq 模型最基础的解码方法是贪心法,即选取一种度量标准后,每次都在当前状态下选择最佳的一个结果,直到结束。贪心法的计算代价低,适合作为基准结果与其他方法相比较。贪心法获得的是一个局部最优解,由于实际问题的复杂性,该方法往往不能取得最好的结果。
集束搜索: 是一种启发式算法,会保存 beam size 个当前的较佳选择,然后解码时每一步根据保存的选则进行下一步扩展和排序,接着选择前 b 个进行保存,循环迭代,知道结束时选择最佳的一个作为解码的结果。 b 往往选择一个适中的范围,以 8-12 为佳。
Seq2Seq 模型引入注意力机制是为了解决什么问题?为什么选用了双向的循环神经网络模型?
编码时输入序列的全部信息压缩到了一个向量中,随着序列增长,句子越前面的词的信息丢失越严重。同时,Seq2Seq 模型的输出序列中,常常会损失部分输入序列信息,这是解码时,当前词及对应的源语言词的上下文信息和位置信息在编解码过程中丢失了。 引入注意力机制,解决上述问题 。使用双向的循环神经网络进行建模,可以获取前后文的信息。
7. 循环神经网络(RNN)简介
循环神经网络英文名称为 ( Recurrent Neural Network, RNN ),其通过使用带自反馈的神经元,能够处理任意长度的 时序 数据。
给定输入时序序列
式中, 表示一段时序数据, 为时间长度
以一段英文段落为例,其时序数据可以表示为:
若是一段视频,将其每一帧通过CNN网络处理得到相应的编码向量
循环神经网络通过以下公式更新隐藏层的活性值
循环神经网络图示
RNN的基本模型如下图所示,为便于理解,图中将RNN的模型展开,按照时序方向对其前向传播流程进行介绍
RNN的基本模型
利用数学表达式整个过程可以变得更加清晰,RNN的前向传播公式如下:
将上述过程整合到一个RNN cell中,可以表示为如下图所示的过程:
RNN的前向传播示意图
缺陷:
没有利用到模型后续的信息,可以通过双向RNN网络进行优化
RNN主要有两种计算梯度的方式:随时间反向传播(BPTT)和实时循环学习法(RTRL)算法
本文中主要介绍随时间反向传播的方法 ( BackPropagation Through Time )
RNN的损失函数与任务有关,对于同步的序列对序列任务,其loss可以用交叉熵公式表示
然后通过BPTT算法便可以进行梯度的反向传播计算
梯度爆炸的解决方法:梯度修剪
梯度消失的解决方法:增加长程依赖 LSTM,GRU
GRU的基本思路:增加相关门(Relate Gate)和更新门(Update Gate),进而使得RNN单元具有记忆能力
首先从数学角度对GRU的前向传播过程进行介绍,具体公式如下:
公式中各变量的含义:
将上述数学公式转化为图像,可得
GRU Cell的前向传播流程
LSTM意为长短时记忆网络 (Long Short-Term Memory Network,LSTM) ,可以有效地解决简单神经网络的梯度消失和爆炸问题
在LSTM中,与GRU主要有两点不同
同样,先从数学公式入手,对LSTM的前向传播过程进行了解
基于数学公式的过程,可将LSTM CELL的前向传播过程总结为(图片借用于nndl):
LSTM Cell的前向传播示意图
从上图中可以看出,LSTM在前向传播的过程中传输了两个状态:内部状态 以及外部状态 ,在整个传播过程中 外部状态(隐状态) 每个时刻都会被重写,因此可以看作一种 短时记忆 ,而 内部状态 可以在某个时刻捕捉一些关键信息,并将此信息保存一段时间间隔,可以看作一种 长时记忆 (长的短时记忆)
此外,在LSTM网络初始化训练的时候,需要手动将遗忘门的数值设置的大一些,否则在参数初始化的时候,遗忘门的数据会被初始化为一个很小的值,前一时刻的内部状态 大部分都会丢失,这样网络很难获取到长距离的依赖信息,并且相邻时间间隔的梯度会非常小,导致 梯度弥散 问题,因此遗忘门的 偏置变量 的初始值 一般很大,取 1或2
将 设置为1即可,但是长度非常的大的时候会造成记忆单元的饱和,降低性能
三个门不仅依赖于 和 ,也依赖于
将两者合并为一个门,即:
首先,我们要理解什么是深层的RNN,对于单个的RNN cell,若将其在时间维度上展开,其深度与时间维度的长度成正比,但若将一个RNN cell看作为单个从 的映射函数,则单个cell实际上是很浅显的一层,因此深层循环神经网络要做的就是把多个RNN cell组合起来,换句话说,就是增加从输入 到输出 的路径,使得网络的深度更深。
如何增加从输入 到输出 的路径呢?两种途径:
堆叠循环神经网络示意图
将网络带入到实际应用场景中:假如我们要翻译一段句子
在这里,is和are实际上是由后面的Lucy和they所决定的,而这种单向的按照时序进行传播的方式没有利用到后面的信息。因此诞生了双向循环网络
双向循环神经网络示意图
双向循环神经网络实际上就是简单的双层循环神经网络,只不过第二层网络的传播方式为按时序的逆向传播,其传播公式为:
8. 深层神经网络的超参数调试、正则化及优化
训练集 ( Training set )
作用是用来拟合模型,通过设置分类器的参数,训练分类模型。后续结合验证集作用时,会选出同一参数的不同取值,拟合出多个分类器。
验证集 ( Dev set )
作用是当通过训练集训练出多个模型后,为了能找出效果最佳的模型,使用各个模型对验证集数据进行预测,并记录模型准确率。选出效果最佳的模型所对应的参数,即用来调整模型参数。如svm中的参数c和核函数等。
测试集 ( Test set )
通过训练集和验证集得出最优模型后,使用测试集进行模型预测。用来衡量该最优模型的性能和分类能力。即可以把测试集当做从来不存在的数据集,当已经确定模型参数后,使用测试集进行模型性能评价。
一个有助于理解的形象比喻:
训练集 —— 课本,学生根据课本里的内容来掌握知识。
验证集 —— 作业,通过作业可以知道 不同学生学习情况、进步的速度快慢。
测试集 —— 考试,考的题是平常都没有见过,考察学生举一反三的能力。
训练集 直接参与了模型调参的过程,显然不能用来反映模型真实的能力(防止课本死记硬背的学生拥有最好的成绩,即防止 过拟合 ) 。
验证集 参与了人工调参(超参数)的过程,也不能用来最终评判一个模型(刷题库的学生不代表其学习能力强)。
所以要通过最终的考试 (测试集) 来考察一个学生(模型)真正的能力。
如何将只有一个包含m个样例的数据集D,产生出训练集S和测试集T(验证集可以省略)?主要有以下三种方法:
自助法 ( bootstrapping )
给定m个样本的数据集D,我们对它进行采样产生数据集D',每次随机从D中挑选一个样本,将其拷贝入D',然后再将样本放回原始数据集D。显然,该样本在下次采样时任然有可能被采到。这个过程重复m次后,我们就得到了含有m个样本的数据集D',这就是自助采样的结果。 样本有重复采样,也有一次也没有被采到的。从未采到的结果是 ,取极限得到
因此,使用自助法约有1/3的数据集没有被选中过,它们用于测试,这种方式叫“外包估计”。
自助法在数据集小,难以划分训练集、测试集的时候有很大的效果,如果数据集足够大的时候,留出法和交叉验证是更好的选择。
留出法 ( hold-out )
将整个数据集D划分为两个互斥的集合,其中一个作为训练集S,另一个作为测试集T。即,D=S∪T,S∩T=∅。在S上训练出模型,T作为测试集,来评估模型效果。
当样本数据量较小(10000条左右及以下)时,通常取其中70%作为训练集,30%作为测试集;或60%作为训练集,验证集和测试集各20%。
交叉验证法 ( cross validation )
如图所示,交叉验证法的实现流程大致如下:
(1) 将整个数据集分成k个大小相似的子集,即D=D1∪D2∪...∪Dk,Di∩Dj=∅(故又称k折交叉验证法,通常取k=10 )。
(2) 对于每一个模型Mi,算法执行k次,每次选择一个Sj(1≤j≤k)作为测试集,其它作为训练集来训练模型Mi,把训练得到的模型在Sj上进行测试,这样一来,每次都会得到一个误差E,最后对k次得到的误差求平均,就可以得到模型Mi的泛化误差。
(3) 算法选择具有最小泛化误差的模型作为最终模型,并且在整个训练集上再次训练该模型,从而得到最终的模型。
交叉验证的主要的目的是 为了选择不同的模型类型(比如一次线性模型、非线性模型) ,而 不是为了选择具体模型的具体参数 。比如在BP神经网络中,其目的主要为了选择模型的层数、神经元的激活函数、每层模型的神经元个数(即所谓的超参数),每一层网络神经元连接的最终权重是在模型选择(即K折交叉验证)之后,由全部的训练数据重新训练。
假设这就是数据集,显然用简单分类器(如逻辑回归)并不能很好地拟合上述数据。这种情况称为 欠拟合 。
相反地,如果采用一个非常复杂的分类器(如深度神经网络或含有隐藏单元的神经网络),拟合效果会非常好。但与此同时,模型的复杂度也会过高,这种称为 过拟合 。
在两者之间,可能会存在一些复杂程度适中、数据拟合适度的分类器,拟合结果较为合理,称为 适度拟合 。
如上图所示,训练集误差和验证集误差均较高时为 高偏差(欠拟合) 情况;训练集误差较高,验证集误差较高低时为 高方差(过拟合) 情况。
(1) 如何减小偏差(防止欠拟合)
① 增大神经网络规模。
(2) 如何减小方差(防止过拟合)
① 增加数据集样本数量;
② 正则化。
参数 是指神经网络中由数据驱动并进行调整的变量,如𝑊和𝑏。
超参数 是指无需数据驱动,而是在训练前或者训练中人为进行调整的变量。例如算法中的learning rate 𝑎(学习率)、iterations(梯度下降法循环的数量)、𝐿(隐藏层数目)、𝑛[𝑙](隐藏层单元数目)、choice of activation function(激活函数的选择)等都需要人为设置,这些数字实际上控制了最后的参数𝑊和𝑏的值,所以它们被称作超参数。
神经网络中的超参数主要分为三类:网络参数、优化参数、正则化参数。
网络参数
可指网络层与层之间的交互方式(相加、相乘或者串接等)、卷积核数量和卷积核尺寸、网络层数(也称深度)和激活函数等。
优化参数
一般指学习率(learning rate)、批样本数量(batch size)、不同优化器的参数以及部分损失函数的可调参数等。
正则化参数
权重衰减系数,随机失活比率(dropout)等。
正则化有利于减小训练集和验证集准确率的方差,防止过拟合。在无法增加样本数量或增加样本数量的成本过高时,正则化是一种行之有效的方法。
一般将任意 维向量 的 - 范数定义为
根据定义:
当 时, 的 范数为 ,表示向量 中非0元素的个数。
当 时, 的 范数为 ,等于向量 中所有元素的绝对值之和。
当 时, 的 范数为 ,等于向量 中所有元素的平方和开根号。
正则化(Regularization) 的主要目的是控制模型复杂度,减小过拟合。最基本的正则化方法是在原目标(代价)函数 中添加惩罚项,对复杂度高的模型进行“惩罚”。
对于神经网络模型, 正则化即在其代价函数中添加 正则项:
其中, 。之后再求解优化问题 即可。
假设某三层神经网络存在过拟合问题,采用dropout正则化会遍历网络的每一层,并设置消除该层中每一个节点的概率(比如0.5),最后得到一个节点更少、规模更小的网络,然后再用反向传播方法进行训练,就能有效防止过拟合。
最常用的方法是 inverted dropout(反向随机失活) 。对于一个三层神经网络( ),以第三层为例,实施dropout的步骤如下:
① 定义一个三层dropout矩阵d3:
d3=numpy.random.rand(a3.shape[0],a3.shape[1])
其中,a3表示神经网络第三层的激活函数矩阵。
② 设置 ( )的大小。 表示保留某个隐藏单元的概率。将第①步产生的随机矩阵d3的每个元素与 进行比较,小于置1,大于置0,得到新的d3矩阵(1表示保留该节点,0表示删除该节点)。
③ 将a3与新的d3矩阵相乘(矩阵对应元素相乘),得到新的激活函数矩阵:
a3 =np.multiply(a3,d3)
④ 将新的a3矩阵除以keep-prob:
a3 /= keep_prob
目的是保证a3的期望值(均值)不变,从而保证第三层的输出不变。
① 使用dropout可以使得部分节点失活,可以起到简化神经网络结构的作用,从而起到正则化的作用。
② 因为dropout是使得神经网络的节点随机失活,这样会让神经网络在训练的时候不会使得某一个节点权重过大。因为该节点输入的特征可能会被清除,所以神经网络的节点不能依赖任何输入的特征。dropout最终会产生收缩权重的平方范数的效果,来压缩权重,达到类似于 正则化的效果。
① dropout在测试阶段不需要使用,因为如果在测试阶段使用dropout可能会导致预测值产生随机变化(因为dropout使节点随机失活)。而且,在训练阶段已经将权重参数除以keep-prob来保证输出的期望值不变,所以在测试阶段没必要再使用dropout。
② 神经网络的不同层在使用dropout的时候,keep-prob可以不同。因为可能有的层参数比较多,比较复杂,keep-prob可以小一些,而对于结构比较简单的层,keep-prob的值可以大一些甚至为1,keep-prob等于1表示不使用dropout,即该层的所有节点都保留。
加快训练速度。
对于一个神经网络模型,考虑其代价函数:
如果未归一化输入,其代价函数的形状会较为细长狭窄。在这样的代价函数的限制下,为避免陷入局部最优解,梯度下降法的学习率必须设置得非常小。
如果归一化输入,代价函数便呈现球形轮廓。这种情况下,不论从哪个位置开始梯度下降法,都能使用较大的学习率,从而更快速、直接地找到全局最优解。
对于包含n个特征的m个样本的数据集,其输入归一化的过程主要分为两步:
① 零均值化
② 归一化方差
其中, 代表第 个样本的特征矩阵。
训练集、验证集、测试集特征矩阵的平均值 和标准差 要保持一致,确保它们归一化后符合同一分布。
9. AI数学基础14——神经网络的参数和超参数
神经网络的参数( Parameters ),是指神经网络模型内部的配置变量,比如W、b,可以用训练的方式获得
神经网络的超参数( Hyper Parameters) ,是神经网络模型外部的配置参数,比如学习率a、隐藏层数L、隐藏层单元数、激活函数的选择、momentum、mini batch size、regularization parameters等等,这些参数不能从训练中得到, 必须手动设置, 并且影响最后的参数W和b的值 。
训练神经网络的过程,也是系统性调整神经网络超参数的过程;Andrew Ng说:“经常试试不同的超参数,勤于检查结果,看看有没有更好的超参数取值,你将会得到设定超参数的直觉”