1. Pytorch_循环神经网络RNN
RNN是Recurrent Neural Networks的缩写,即循环神经网络,它常用于解决序列问题。RNN有记忆功能,除了当前输入,还把上下文环境作为预测的依据。它常用于语音识别、翻译等场景之中。
RNN是序列模型的基础,尽管能够直接调用现成的RNN算法,但后续的复杂网络很多构建在RNN网络的基础之上,如Attention方法需要使用RNN的隐藏层数据。RNN的原理并不复杂,但由于其中包括循环,很难用语言或者画图来描述,最好的方法是自己手动编写一个RNN网络。本篇将介绍RNN网络的原理及具体实现。
在学习循环神经网络之前,先看看什么是序列。序列sequence简称seq,是有先后顺序的一组数据。自然语言处理是最为典型的序列问题,比如将一句话翻译成另一句话时,其中某个词汇的含义不仅取决于它本身,还与它前后的多个单词相关。类似的,如果想预测电影的情节发展,不仅与当前的画面有关,还与当前的一系列前情有关。在使用序列模型预测的过程中,输入是序列,而输出是一个或多个预测值。
在使用深度学习模型解决序列问题时, 最容易混淆的是,序列与序列中的元素 。在不同的场景中,定义序列的方式不同,当分析单词的感情色彩时,一个单词是一个序列seq;当分析句子感情色彩时,一个句子是一个seq,其中的每个单词是序列中的元素;当分析文章感情色彩时,一篇文章是一个seq。简单地说,seq是最终使用模型时的输入数据,由一系列元素组成。
当分析句子的感情色彩时,以句为seq,而句中包含的各个单词的含义,以及单词间的关系是具体分析的对象,此时,单词是序列中的元素,每一个单词又可有多维特征。从单词中提取特征的方法将在后面的自然语言处理中介绍。
RNN有很多种形式,单个输入单个输入;多个输入多个输出,单个输入多个输出等等。
举个最简单的例子:用模型预测一个四字短语的感情色彩,它的输入为四个元素X={x1,x2,x3,x4},它的输出为单个值Y={y1}。字的排列顺序至关重要,比如“从好变坏”和“从坏变好”,表达的意思完全相反。之所以输入输出的个数不需要一一对应,是因为中间的隐藏层,变向存储中间信息。
如果把模型设想成黑盒,如下图所示:
如果模型使用全连接网络,在每次迭代时,模型将计算各个元素x1,x2...中各个特征f1,f2...代入网络,求它们对结果y的贡献度。
RNN网络则要复杂一些,在模型内部,它不是将序列中所有元素的特征一次性输入模型,而是每一次将序列中单个元素的特征输入模型,下图描述了RNN的数据处理过程,左图为分步展示,右图将所有时序步骤抽象成单一模块。
第一步:将第一个元素x1的特征f1,f2...输入模型,模型根据输入计算出隐藏层h。
第二步:将第二个元素x2的特征输入模型,模型根据输入和上一步产生的h再计算隐藏层h,其它元素以此类推。
第三步:将最后一个元素xn的特征输入模型,模型根据输入和上一步产生的h计算隐藏层h和预测值y。
隐藏层h可视为将序列中前面元素的特征和位置通过编码向前传递,从而对输出y发生作用,隐藏层的大小决定了模型携带信息量的多少。隐藏层也可以作为模型的输入从外部传入,以及作为模型的输出返回给外部调用。
本例仍使用上篇中的航空乘客序列数据,分别用两种方法实现RNN:自己编写程序实现RNN模型,以及调用Pytorch提供的RNN模型。前一种方法主要用于剖析原理,后一种用于展示常用的调用方法。
首先导入头文件,读取乘客数据,做归一化处理,并将数据切分为测试集和训练集,与之前不同的是加入了create_dataset函数,用于生成序列数据,序列的输入部分,每个元素中包括两个特征:前一个月的乘客量prev和月份值mon,这里的月份值并不是关键特征,主要用于在例程中展示如何使用多个特征。
第一步:实现模型类,此例中的RNN模型除了全连接层,还生成了一个隐藏层,并在下一次前向传播时将隐藏层输出的数据与输入数据组合后再代入模型运算。
第二步,训练模型,使用全部数据训练500次,在每次训练时,内部for循环将序列中的每个元素代入模型,并将模型输出的隐藏层和下一个元素一起送入下一次迭代。
第三步:预测和作图,预测的过程与训练一样,把全部数据拆分成元素代入模型,并将每一次预测结果存储在数组中,并作图显示。
需要注意的是,在训练和预测过程中,每一次开始输入新序列之前,都重置了隐藏层,这是由于隐藏层的内容只与当前序列相关,序列之间并无连续性。
程序输出结果如下图所示:
经过500次迭代,使用RNN的效果明显优于上一篇中使用全连接网络的拟合效果,还可以通过调整超参数以及选择不同特征,进一步优化。
使用Pytorch提供的RNN模型,torch.nn.RNN类可直接使用,是循环网络最常用的解决方案。RNN,LSTM,GRU等循环网络都实现在同一源码文件torch/nn/moles/rnn.py中。
第一步:创建模型,模型包含两部分,第一部分是Pytorch提供的RNN层,第二部分是一个全连接层,用于将RNN的输出转换成输出目标的维度。
Pytorch的RNN前向传播允许将隐藏层数据h作为参数传入模型,并将模型产生的h和y作为函数返回值。形如: pred, h_state = model(x, h_state)
什么情况下需要接收隐藏层的状态h_state,并转入下一次迭代呢?当处理单个seq时,h在内部前向传递;当序列与序列之间也存在前后依赖关系时,可以接收h_state并传入下一步迭代。另外,当模型比较复杂如LSTM模型包含众多参数,传递会增加模型的复杂度,使训练过程变慢。本例未将隐藏层转到模型外部,这是由于模型内部实现了对整个序列的处理,而非处理单个元素,而每次代入的序列之间又没有连续性。
第二步:训练模型,与上例中把序列中的元素逐个代入模型不同,本例一次性把整个序列代入了模型,因此,只有一个for循环。
Pythorch支持批量处理,前向传递时输入数据格式是[seq_len, batch_size, input_dim),本例中输入数据的维度是[100, 1, 2],input_dim是每个元素的特征数,batch_size是训练的序列个数,seq_len是序列的长度,这里使用70%作为训练数据,seq_len为100。如果数据维度的顺序与要求不一致,一般使用transpose转换。
第三步:预测和作图,将全部数据作为序列代入模型,并用预测值作图。
程序输出结果如下图所示:
可以看到,经过500次迭代,在前100个元素的训练集上拟合得很好,但在测试集效果较差,可能存在过拟合。
2. 从动图中理解 RNN,LSTM 和 GRU
递归神经网络(RNNs)是一类常用的序列数据人工神经网络。三种最常见的递归神经网络类型分别是:
要指出的一点是,我将使用"RNNS"来统称本质上是递归神经网络结构,"vanilla RNN"来指代在图一所展示的最简单的循环神经网络结构.
有很多关于递归神经网络的图解.
我个人最喜欢的一个是Michael Nguyen发表在《走向数据科学》(Towards Data Science)的这篇文章,因为他不仅给我们提供了对这些模型的直觉,更重要的是这些漂亮的插图,使我们更容易理解。但我发表这篇文章的动机是为了更好地理解这些单元中发生了什么,节点是如何共享的,以及它们是如何转换为输出节点。这里,我也受到了Michael的动画启发。
本文研究了vanilla RNN、LSTM和GRU单元。这是一个简短的概述,是为那些读过关于这些主题的文章的人准备的。(我建议在阅读本文之前先阅读Michael的文章),需要注意的是,以下动画是按顺序引导的,但在向量化的机器计算过程中并不反映时间上的顺序。
下面是我用来做说明的图例:
图0:动画图例
在我的动画中,我使用了大小为3(绿色)的输入和2个隐藏单元(红色),批量大小为1。
让我们开始吧!
图1:vanilla RNN 示意动画
图2:LSTM 示意动画
注意,单元状态的维度与隐藏状态的维度相同。
图3:GRU 示意动画
希望这些动画能以某种方式帮助你!以下是静态图像中的概况:
图4:Vanilla RNN 单元
图5:LSTM 单元
图6:GRU 单元
一个提醒:我使用Google绘图来创建的这些示意图。
想要继续查看该篇文章相关链接和参考文献?雷锋网雷锋网雷锋网
点击【从动图中理解 RNN,LSTM 和 GRU】即可访问!
今日资源推荐: CCF-GAIR | 张大鹏教授演讲 PPT:生物特征识别的新进展 - 纪念中国人工智能40年
非常高兴受邀参加本次会议,让我有机会汇报我的最新工作。今天我的讲题是“纪念中国人工智能40周年”,而我本人是中国学位法公布后首届入学的研究生,也是哈工大毕业的首个计算机博士,从 1980 年入学开始算起,我基本见证了中国人工智能这 40 年的发展历程。
这是我研究生期间所能找到最早的一篇论文,选题与指纹识别有关。 1984 年,陈光熙教授是我的博士生导师,图片展示的是当年哈工大进行博士学位论文答辩的场景。
点击链接获取:https://ai.yanxishe.com/page/resourceDetail/905
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)简介
循环神经网络英文名称为 ( 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所决定的,而这种单向的按照时序进行传播的方式没有利用到后面的信息。因此诞生了双向循环网络
双向循环神经网络示意图
双向循环神经网络实际上就是简单的双层循环神经网络,只不过第二层网络的传播方式为按时序的逆向传播,其传播公式为:
5. 循环神经网络(RNN)的应用
循环神经网络(RNN)是目前深度学习最有前景的工具之一,它解决了传统神经网络不能共享从数据中共享位置的特征的问题。目前,RNN已经有了不少有意思的应用:
语音识别 :输入的语音数据,生成相应的语音文本信息。比如微信的语音转文字功能。
机器翻译 :不同语言之间的相互转换。像有道翻译、腾讯翻译官等。最近微软据说实现了中翻英媲美人类的水平
音乐生成 :使用RNN网络生成音乐,一般会用到RNN中的LSTM算法(该算法可以解决RNN网络中相距较远的节点梯度消失的问题)。下面这个github项目实现了jazz音乐的生成。
deepjazz
文本生成 :利用RNN亦可以生成某种风格的文字。有兴趣的可以看一下一下两个github项目
numpy实现字符层面的文本生成器
keras实现特定作家风格的文本
情感分类 :输入文本或者语音的评论数据,输出相应的打分数据。
DNA序列分析 :输入的DNA序列,输出蛋白质表达的子序列。
视频行为识别 :识别输入的视频帧序列中的人物行为。
实体名字识别 :从文本中识别实体的名字。
6. 理解 LSTM 网络
作者 : Christopher Olah (OpenAI)
译者 :朱小虎 Xiaohu (Neil) Zhu(CSAGI / University AI)
原文链接 : https://colah.github.io/posts/2015-08-Understanding-LSTMs/
术语 : 循环神经网络(Recurrent Neural Network, 简称 RNN); 长短期记忆(Long Short-Term Memory, 简称 LSTM); 门限循环单元(Gated Recurrent Unit, 简称 GRU)
人类并不是每时每刻都从一片空白的大脑开始他们的思考。在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。
传统的神经网络并不能做到这点,看起来也像是一种巨大的弊端。例如,假设你希望对电影中的每个时间点的时间类型进行分类。传统的神经网络应该很难来处理这个问题——使用电影中先前的事件推断后续的事件。
RNN 解决了这个问题。RNN 是包含循环的网络,允许信息的持久化。
在上面的示例图中,神经网络的模块, ,正在读取某个输入 ,并输出一个值 。循环可以使得信息可以从当前步传递到下一步。
这些循环使得 RNN 看起来非常神秘。然而,如果你仔细想想,这样也不比一个正常的神经网络难于理解。RNN 可以被看做是同一神经网络的多次复制,每个神经网络模块会把消息传递给下一个。所以,如果我们将这个循环展开:
链式的特征揭示了 RNN 本质上是与序列和列表相关的。他们是对于这类数据的最自然的神经网络架构。
并且 RNN 也已经被人们应用了!在过去几年中,应用 RNN 在语音识别,语言建模,翻译,图片描述等问题上已经取得一定成功,并且这个列表还在增长。我建议大家参考 Andrej Karpathy 的博客文章—— The Unreasonable Effectiveness of Recurrent Neural Networks 来看看更丰富有趣的 RNN 的成功应用。
而这些成功应用的关键之处就是 LSTM 的使用,这是一种特别的 RNN,比标准的 RNN 在很多的任务上都表现得更好。几乎所有的令人振奋的关于 RNN 的结果都是通过 LSTM 达到的。这篇博文也会就 LSTM 进行展开。
RNN 的关键点之一就是他们可以用来连接先前的信息到当前的任务上,例如使用过去的视频段来推测对当前段的理解。如果 RNN 可以做到这个,他们就变得非常有用。但是真的可以么?答案是,还有很多依赖因素。
有时候,我们仅仅需要知道先前的信息来执行当前的任务。例如,我们有一个语言模型用来基于先前的词来预测下一个词。如果我们试着预测 “the clouds are in the sky” 最后的词,我们并不需要任何其他的上下文 —— 因此下一个词很显然就应该是 sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN 可以学会使用先前的信息。
但是同样会有一些更加复杂的场景。假设我们试着去预测“I grew up in France... I speak fluent French”最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France 的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。
不幸的是,在这个间隔不断增大时,RNN 会丧失学习到连接如此远的信息的能力。
在理论上,RNN 绝对可以处理这样的 长期依赖 问题。人们可以仔细挑选参数来解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。 Bengio, et al. (1994) 等人对该问题进行了深入的研究,他们发现一些使训练 RNN 变得非常困难的相当根本的原因。
然而,幸运的是,LSTM 并没有这个问题!
Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息。LSTM 由 Hochreiter & Schmidhuber (1997) 提出,并在近期被 Alex Graves 进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。
LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层。
LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于 单一神经网络层,这里是有四个,以一种非常特殊的方式进行交互。
不必担心这里的细节。我们会一步一步地剖析 LSTM 解析图。现在,我们先来熟悉一下图中使用的各种元素的图标。
在上面的图例中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。粉色的圈代表按位 pointwise 的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。
LSTM 的关键就是细胞状态,水平线在图上方贯穿运行。
细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。
LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个按位的乘法操作。
Sigmoid 层输出 到 之间的数值,描述每个部分有多少量可以通过。 代表“不许任何量通过”, 就指“允许任意量通过”!
LSTM 拥有三个门,来保护和控制细胞状态。
在我们 LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。这个决定通过一个称为 忘记门层 完成。该门会读取 和 ,输出一个在 到 之间的数值给每个在细胞状态 中的数字。 表示“完全保留”, 表示“完全舍弃”。
让我们回到语言模型的例子中来基于已经看到的预测下一个词。在这个问题中,细胞状态可能包含当前 主语 的性别,因此正确的 代词 可以被选择出来。当我们看到新的 主语 ,我们希望忘记旧的 主语 。
下一步是确定什么样的新信息被存放在细胞状态中。这里包含两个部分。第一, sigmoid 层称 “输入门层” 决定什么值我们将要更新。然后,一个 tanh 层创建一个新的候选值向量, ,会被加入到状态中。下一步,我们会讲这两个信息来产生对状态的更新。
在我们语言模型的例子中,我们希望增加新的主语的性别到细胞状态中,来替代旧的需要忘记的主语。
现在是更新旧细胞状态的时间了, 更新为 。前面的步骤已经决定了将会做什么,我们现在就是实际去完成。
我们把旧状态与 相乘,丢弃掉我们确定需要丢弃的信息。接着加上 。这就是新的候选值,根据我们决定更新每个状态的程度进行变化。
在语言模型的例子中,这就是我们实际根据前面确定的目标,丢弃旧代词的性别信息并添加新的信息的地方。
最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。首先,我们运行一个 sigmoid 层来确定细胞状态的哪个部分将输出出去。接着,我们把细胞状态通过 tanh 进行处理(得到一个在 到 之间的值)并将它和 sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。
在语言模型的例子中,因为他就看到了一个 代词 ,可能需要输出与一个 动词 相关的信息。例如,可能输出是否代词是单数还是负数,这样如果是动词的话,我们也知道动词需要进行的词形变化。
我们到目前为止都还在介绍正常的 LSTM。但是不是所有的 LSTM 都长成一个样子的。实际上,几乎所有包含 LSTM 的论文都采用了微小的变体。差异非常小,但是也值得拿出来讲一下。
其中一个流形的 LSTM 变体,就是由 Gers & Schmidhuber (2000) 提出的,增加了 “peephole connection”。是说,我们让 门层 也会接受细胞状态的输入。
上面的图例中,我们增加了 peephole 到每个门上,但是许多论文会加入部分的 peephole 而非所有都加。
另一个变体是通过使用 coupled 忘记和输入门。不同于之前是分开确定什么忘记和需要添加什么新的信息,这里是一同做出决定。我们仅仅会当我们将要输入在当前位置时忘记。我们仅仅输入新的值到那些我们已经忘记旧的信息的那些状态 。
另一个改动较大的变体是 Gated Recurrent Unit (GRU),这是由 Cho, et al. (2014) 提出。它将忘记门和输入门合成了一个单一的 更新门。同样还混合了细胞状态和隐藏状态,和其他一些改动。最终的模型比标准的 LSTM 模型要简单,也是非常流行的变体。
这里只是部分流行的 LSTM 变体。当然还有很多其他的,如 Yao, et al. (2015) 提出的 Depth Gated RNN。还有用一些完全不同的观点来解决长期依赖的问题,如 Koutnik, et al. (2014) 提出的 Clockwork RNN。
要问哪个变体是最好的?其中的差异性真的重要吗? Greff, et al. (2015) 给出了流行变体的比较,结论是他们基本上是一样的。 Jozefowicz, et al. (2015) 则在超过 1 万种 RNN 架构上进行了测试,发现一些架构在某些任务上也取得了比 LSTM 更好的结果。
刚开始,我提到通过 RNN 得到重要的结果。本质上所有这些都可以使用 LSTM 完成。对于大多数任务确实展示了更好的性能!
由于 LSTM 一般是通过一系列的方程表示的,使得 LSTM 有一点令人费解。然而本文中一步一步地解释让这种困惑消除了不少。
LSTM 是我们在 RNN 中获得的重要成功。很自然地,我们也会考虑:哪里会有更加重大的突破呢?在研究人员间普遍的观点是:“Yes! 下一步已经有了——那就是 注意力 !” 这个想法是让 RNN 的每一步都从更加大的信息集中挑选信息。例如,如果你使用 RNN 来产生一个图片的描述,可能会选择图片的一个部分,根据这部分信息来产生输出的词。实际上, Xu, et al. (2015) 已经这么做了——如果你希望深入探索 注意力 可能这就是一个有趣的起点!还有一些使用注意力的相当振奋人心的研究成果,看起来有更多的东西亟待探索……
注意力也不是 RNN 研究领域中唯一的发展方向。例如, Kalchbrenner, et al. (2015) 提出的 Grid LSTM 看起来也是很有前途。使用生成模型的 RNN,诸如 Gregor, et al. (2015) Chung, et al. (2015) 和 Bayer & Osendorfer (2015) 提出的模型同样很有趣。在过去几年中,RNN 的研究已经相当的燃,而研究成果当然也会更加丰富!
I’m grateful to a number of people for helping me better understand LSTMs, commenting on the visualizations, and providing feedback on this post.
I’m very grateful to my colleagues at Google for their helpful feedback, especially Oriol Vinyals , Greg Corrado , Jon Shlens , Luke Vilnis , and Ilya Sutskever . I’m also thankful to many other friends and colleagues for taking the time to help me, including Dario Amodei , and Jacob Steinhardt . I’m especially thankful to Kyunghyun Cho for extremely thoughtful correspondence about my diagrams.
Before this post, I practiced explaining LSTMs ring two seminar series I taught on neural networks. Thanks to everyone who participated in those for their patience with me, and for their feedback.
7. CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构有什么区别
如下:
1、DNN:存在着一个问题——无法对时间序列上的变化进行建模。然而,样本出现的时间顺序对于自然语言处理、语音识别、手写体识别等应用非常重要。对了适应这种需求,就出现了另一种神经网络结构——循环神经网络RNN。
2、CNN:每层神经元的信号只能向上一层传播,样本的处理在各个时刻独立,因此又被称为前向神经网络。
3、RNN:神经元的输出可以在下一个时间戳直接作用到自身,即第i层神经元在m时刻的输入,除了(i-1)层神经元在该时刻的输出外,还包括其自身在(m-1)时刻的输出!
介绍
神经网络技术起源于上世纪五、六十年代,当时叫感知机(perceptron),拥有输入层、输出层和一个隐含层。输入的特征向量通过隐含层变换达到输出层,在输出层得到分类结果。早期感知机的推动者是Rosenblatt。
在实际应用中,所谓的深度神经网络DNN,往往融合了多种已知的结构,包括卷积层或是LSTM单元。
8. 循环神经网络
花书中关于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)输出门
9. DNN、RNN、CNN分别是什么意思
DNN(深度神经网络),是深度学习的基础。
DNN可以理解为有很多隐藏层的神经网络。这个很多其实也没有什么度量标准, 多层神经网络和深度神经网络DNN其实也是指的一个东西,当然,DNN有时也叫做多层感知机(Multi-Layer perceptron,MLP)。
从DNN按不同层的位置划分,DNN内部的神经网络层可以分为三类,输入层,隐藏层和输出层,如下图示例,一般来说第一层是输出层,最后一层是输出层,而中间的层数都是隐藏层。
CNN(卷积神经网络),是一种前馈型的神经网络,目前深度学习技术领域中非常具有代表性的神经网络之一。
CNN在大型图像处理方面有出色的表现,目前已经被大范围使用到图像分类、定位等领域中。相比于其他神经网络结构,卷积神经网络需要的参数相对较少,使的其能够广泛应用。
RNN(循环神经网络),一类用于处理序列数据的神经网络,RNN最大的不同之处就是在层之间的神经元之间也建立的权连接。
从广义上来说,DNN被认为包含了CNN、RNN这些具体的变种形式。在实际应用中,深度神经网络DNN融合了多种已知的结构,包含卷积层或LSTM单元,特指全连接的神经元结构,并不包含卷积单元或时间上的关联。