前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【算法】循环神经网络RNN

【算法】循环神经网络RNN

作者头像
陆勤_数据人网
发布2018-04-18 16:57:45
1.2K0
发布2018-04-18 16:57:45
举报

小编邀请您,先思考:

1 RNN和LSTM有什么异同?

2 RNN的输入和输出分别是什么?

3 如何用Python实现RNN?

传统的机器学习方法,如SVM、logistics回归和前馈神经网络都没有将时间进行显式模型化,用这些方法来建模都是基于输入数据独立性假设的前提。但是,对于很多任务而言,这非常局限。举个例子,假如你想根据一句没说完的话,预测下一个单词,最好的办法就是联系上下文的信息。下面有两种解决方案

1.一种思路是记忆之前的分类器的状态,在这个基础上训练新的分类器,从而结合历史影响,但是这样需要大量历史分类器

2.重用分类器,只用一个分类器总结状态,其他分类器接受对应时间的训练,然后传递状态,这样就避免了需要大量历史分类器,而且还比较有效的解决了这个问题。而这样一种东西是什么呢?没错,就是 RNN(循环神经网络)

RNN 之所以称为循环神经网路,是因为一个序列当前的输出与前面的输出有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,也就是说隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。

下面是一个典型的RNN模型:

研究一下模型的输入和输出。以输入句子为例,输入的句子中第t个单词进行Embedding之后的向量表达作为网络t时刻的输入,而输入层神经元个数和Embedding的向量长度相符。每个时刻的输出是一个概率分布向量,其中最大值的下标决定了输出哪个词。如果输入的序列中有4个单词,那么,横向展开网络后将有四个神经网络,一个网络对应一个单词,即RNN是在time_step上进行拓展。

下面解释一下图中的计算公式:

· Xt是在时刻t时的输入。例如,X2对应于一个句子的第二个词的实数向量。

· St是在时刻t时的隐藏状态,类似于网络的“大脑”,也就是“记忆模块”的值。St的运算是基于以前隐藏状态St-1和当前的输入Xt决定,其中,f通常是非线性的,例如,tanh、ReLU函数。在计算第一个隐藏状态时,初始值通常设为0。

· Ot是时刻t时的输出结果。如推测句子中的下一个词时,这里的输出就可以表示为一个词典序列,值为每一个词的概率。

需要注意的是:

1. RNN是在时间上共享参数。这意味着这个模型在每个时间步上对输入的处理是一样的,只是输入不同。这样的方式大幅降低了需要学习的参数总数,减少了很多计算量。深度学习是怎么减少参数的,很大原因就是参数共享,其中像CNN 是在空间上共享参数,RNN 是在时间上(顺序上)共享参数。

2. 在上面的图片中显示,不同的时间节点会产生不同的结构输出。但是,不同任务中,有一些输出则是多余的。例如,在情感分析里,我们只关心这个句子最终表达的情绪,而不是每一个单词表达的情绪。同样的,也不是必须得在每一个时间点都有输入。

这就产生了RNN的不同架构,下面是几种RNN 组成的常用架构。

1是普通的单个神经网络,2是把单一输入转化为序列输出,3是把序列输入转化为单个输出,4是把序列转化为序列,也就是 seq2seq的做法,5是无时差的序列到序列转化,可以作为普通的语言模型。

下面再说说几个比较重要的架构:

One to many:

这种情况有两种方式,一种是只在序列开始进行输入计算。

还有一种结构是把输入信息 x 作为每个阶段的输入:

这种one to many的结构可以处理的问题有挺多的,比如图片标注,输入的 x 是图像的特征,而输出的y序列是一段句子或者从类别生成语音或音乐。

may to one

输入是一个序列,输出是一个单独的值而不是序列。这种结构通常用来处理序列分类问题。如输入一段文字判别它所属的类别,输入一个句子判断其情感倾向,输入一段文档并判断它的类别等等。具体如下图:

N to N

输入和输出序列是等长的。这种可以作为简单的Char RNN 可以用来生成文章,诗歌,甚至是代码,非常有意思)。

N to M

这种结构又叫 Encoder-Decoder 模型,也可以称之为 Seq2Seq 模型。在实现问题中,我们遇到的大部分序列都是不等长的,如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。而 Encoder-Decoder 结构先将输入数据编码成一个上下文向量c,之后在通过这个上下文向量输出预测序列。

注意,很多时候只用上下文向量 C 效果并不是很好,而 attention 技术很大程度弥补了这点。seq2seq的应用的范围非常广泛,机器翻译,文本摘要,阅读理解,对话生成....。

再来看看训练算法BPTT

如果将 RNN 进行网络展开,那么参数 W,U,V 是共享的,且在使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,并且还用前面若干步网络的状态。比如,在t=4时,我们还需要向后传递三步,以及后面的三步都需要加上各种的梯度。该学习算法称为Backpropagation Through Time (BPTT)。需要注意的是,在普通 RNN 训练中,BPTT 无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为 BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。当然,有很多方法去解决这个问题,如 LSTM、GRU便是专门应对这种问题的。下面详细介绍一下BPTT。

考虑最前面介绍的RNN网络结构。

将损失函数定义为交叉熵损失函数:

这里,我们将一个完整的句子序列视作一个训练样本,因此总误差即为各时间步(单词)的误差之和。

我们的目的是要计算误差对应的参数U、V和W的梯度,然后借助SGD算法来更新参数。借助导数的链式法则来计算梯度,从最后一层将误差向前传播的思想。

误差函数E对参数V的求导与输入的序列特性没有关系。但是,对参数W的求导则不同。最后可以化成:

可以从这张图直观了解BPTT。

前面就提到BPTT容易带来梯度消失或梯度爆炸的问题,可以从下图直观看出。

我们看看梯度消失的情况,梯度值迅速以指数形式收缩,最终在几个时间步长后完全消失。“较远”的时间步长贡献的梯度变为0,这些时间段的状态不会对你的学习有所贡献:你最终还是无法学习长期依赖。梯度消失不仅存在于循环神经网络,也出现在深度前馈神经网络中。区别在于,循环神经网络非常深(本例中,深度与句长相同),因此梯度消失问题更为常见。RNN的梯度是非常不稳定的,所以梯度在损失表面的跳跃度是非常大的,也就是说优化程序可能将最优值带到离真实最优值很远的地方。

幸运的是,目前有一些方法可解决梯度消失问题。合理初始化矩阵W可缓解梯度消失现象,还可采用正则化方法。此外,更好的方法是使用 ReLU,而非tanh或sigmoid激活函数(梯度消失有一部分原因是因为激活函数一些性质造成的)。ReLU函数的导数是个常量,0或1,因此不太可能出现梯度消失现象。

更常用的方法是借助LSTM或GRU架构。1997年,首次提出LSTM,目前该模型在NLP领域的应用极其广泛。GRU则于2014年问世,是LSTM的简化版。这些循环神经网络旨在解决梯度消失和有效学习长期依赖问题。

先来看看LSTM。

LSTM通过引入一个叫做“门”(gating)的机制来缓解梯度消失问题。首先,我们要注意LSTM层仅仅是计算隐藏层的另一种方式。

在传统的RNN中,我们用S_t = tanh(Ux_t + Ws_)这个式子来计算隐藏层。其中,隐藏层的输入单元有两个,一个是当前时刻t的输入x_t以及前一时刻的隐藏状态s_。LSTM单元的功能与之相同,只是方式不同而已。这是理解LSTM的关键。你基本上可将LSTB(和GRU)单元视为黑匣子,只要你给定当前输入和前一时刻的隐藏状态,便可计算出下一隐藏状态。如下图:

LSTM的内部结构:

LSTM比RNN多了一个细胞状态,就是最上面一条线,像一个传送带,它让信息在这条线上传播而不改变信息。

LSTM可以自己增加或移除信息,通过“门”的结构控制。

“门”选择性地让信息是否通过,“门”包括一个sigmoid层和按元素乘。如下图:

sigmoid层输出0-1的值,表示让多少信息通过,1表示让所有的信息都通过。

一个LSTM单元有3个门。三个sigmoid层是三个门:忘记门、输入门、输出门。

忘记门:扔掉信息(细胞状态)

第一步是决定从细胞状态里扔掉什么信息(也就是保留多少信息)。将上一步细胞状态中的信息选择性的遗忘 。

实现方式:通过sigmoid层实现的“忘记门”。以上一步的ht−1和这一步的xt

作为输入,然后为Ct−1里的每个数字输出一个0-1间的值,表示保留多少信息(1代表完全保留,0表示完全舍弃),然后与Ct−1乘。

例子:让我们回到语言模型的例子中来基于已经看到的预测下一个词。在这个问题中,细胞状态可能包含当前主语的类别,因此正确的代词可以被选择出来。当我们看到新的主语,我们希望忘记旧的主语。

例如,他今天有事,所以我…… 当处理到“我”的时候选择性的忘记前面的“他”,或者说减小这个词对后面词的作用。

输入层门:存储信息(细胞状态)

第二步是决定在细胞状态里存什么。将新的信息选择性的记录到细胞状态中。

实现方式:包含两部分,1. sigmoid层(输入门层)决定我们要更新什么值;2. tanh层创建一个候选值向量Ct~,将会被增加到细胞状态中。 我们将会在下一步把这两个结合起来更新细胞状态。

例子:在我们语言模型的例子中,我们希望增加新的主语的类别到细胞状态中,来替代旧的需要忘记的主语。 例如:他今天有事,所以我…… 当处理到“我”这个词的时候,就会把主语我更新到细胞中去。

更新细胞状态(细胞状态)

更新旧的细胞状态

实现方式:Ct=ft∗Ct−1+it∗Ct~,ft表示保留上一次的多少信息,it表示更新哪些值,Ct~表示新的候选值。候选值被要更新多少(即it)放缩。

这一步我们真正实现了移除哪些旧的信息(比如一句话中上一句的主语),增加哪些新信息。

输出层门:输出(隐藏状态)

最后,我们要决定作出什么样的预测。

实现方式:1. 我们通过sigmoid层(输出层门)来决定输出新的细胞状态的哪些部分;2. 然后我们将细胞状态通过tanh层(使值在-1~1之间),然后与sigmoid层的输出相乘。

所以我们只输出我们想输出的部分。

例子:在语言模型的例子中,因为它就看到了一个代词,可能需要输出与一个 动词相关的信息。例如,可能输出是否代词是单数还是复数,这样如果是动词的话,我们也知道动词需要进行的词形变化。

例如:上面的例子,当处理到“我”这个词的时候,可以预测下一个词,是动词的可能性较大,而且是第一人称。 会把前面的信息保存到隐层中去。

LSTM反向传播比较麻烦。

接下来是GRU模型。理解了LSTM的话,GRU就简单了,GRU可以说是LSTM的简化版。其原理与LSTM非常相似,方程式也几乎相同,如下:

GRU有两个门:重置(reset)门r和更新(update)门z。直观来讲,重置门决定了新的输入与前一时刻记忆的组合方式,更新门则决定了先前记忆信息的保留程度。如果将所有重置门设为1,所有更新门设为0,即可再次得到传统的RNN模型。

我们发现,GRU中用门机制来实现学习长期记忆的基本原理与LSTM相同,但也有一些区别:

· GRU有两个门,而LSTM有三个门。

· GRU中不存在区别于内部记忆单元(c_t),也没有LSTM中的输出门。

· LSTM的输入门和遗忘门,在GRU中被整合成一个更新门z;而重置门r被直接用到前一个隐藏状态上面了。

经过实验,一般认为,LSTM和GRU之间并没有明显的优胜者。因为GRU具有较少的参数,所以训练速度快,而且所需要的样本也比较少。而LSTM具有较多的参数,比较适合具有大量样本的情况,可能会获得较优的模型。

对于我们,其实了解一下模型的输入输出也就差不多了,哈哈!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学与人工智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
机器翻译
机器翻译(Tencent Machine Translation,TMT)结合了神经机器翻译和统计机器翻译的优点,从大规模双语语料库自动学习翻译知识,实现从源语言文本到目标语言文本的自动翻译,目前可支持十余种语言的互译。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档