好吧,我承认我懒了,好久没有发文了,主要最近真的很忙,忙校招,忙课题,神烦,趁着周末好好研究了一下RNN和LSTM(为了让毕业论文的逼格高一些),我发现RNN,尤其是LSTM,没有CNN那样直白,思想很简单,但学完之后总觉得似懂非懂,所以今天想写这么一篇博客梳理一下自己的学习心得,也希望与大家多多交流,本人才疏学浅,如有说的不合理的地方,请尽管指正。

首先,默认大家对最简单的感知机是了解的,关于深层的神经网络,可以参考我博客的《希望可以是你看到的最直白清晰的CNN讲解 》,可以让你比较好的对深层神经网络的一种有一个理解,也可以辅助你理解深层神经网络本身。

在这篇博客中,我会讲述:
- RNN的思想和结构
- RNN的缺陷进而出现的其变种——LSTM
- RNN的经典模式与变种
- Encoder-Decoder(编码解码模型),在文本领域也称作Seq2Seq模型
- Attention机制
会涉及到一些简单的数学公式,不用感到头痛。
本博文主要参考了一个英文博客:
http://colah.github.io/posts/2015-08-Understanding-LSTMs/
以及其翻译文章:

以及知乎:
https://zhuanlan.zhihu.com/p/28054589(关于seq2seq2和attention机制的部分)

用最简单的过程讲述RNNs与LSTM的故事

1.RNNs-Recurrent Neural Networks

RNNs-循环神经网络,顾名思义,其网络结构中涉及到一些循环的结构。为什么会出现RNN呢,拿四大名著西游记来说吧:如果你直接从书的中部开始看起,那么可能正是孙悟空大战白骨精,孙悟空神通广大法力无边,有透视眼,对,就这个透视眼,学名叫啥?你可能不知道,因为书的这一部分可能没提到,只是说了这个眼睛可以看穿妖精的伪装,而其实在书的最开始,已经介绍了这个技能,叫做火眼金睛,是从太上老君八卦炉里炼出来的,这时,你可能已经明白了,拿文本来说,可能你正在看的信息与前面的信息是有很大相关性的,二者的位置可能很近,比如一字之隔,也可能很远,比如开头和结尾,总之,当前的信息是受到曾经信息的影响的,而传统的神经网络可能无法胜任这样的工作,此时,就出现了循环神经网络——RNNs。

传统的最简单的神经网络如图1所示。



transformer cnn结合_lstm



图1

而接下来就是循环神经网络的结构,如图2所示,假设将W方块和指向它与从它出去的箭头去掉,那么图2就是单隐藏层的神经网络。现在看图2,x是输入,o是输出,U是输入层到隐藏层的权重矩阵;V是隐藏层到输出层的权重矩阵;RNN的核心思想就是循环神经网络的隐藏层的值R不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的值S’。而W就是上一次隐藏层的值S’作为输入时的权重(参数)矩阵。而这个循环过程(S与W这一个循环体)实际上是可以多次循环的,可能还是有些抽象,我们可以把他展开,如图3所示。



transformer cnn结合_lstm_02



图2

transformer cnn结合_lstm_03


图3

这个网络在t时刻接收到输入xt之后,隐藏层的值是st,输出值是ot。关键一点是,st 的值不仅仅取决于xt,还取决于st−1 。这个过程只是把图2的循环体展开来看,就相当用用显微镜对图2的过程进行观察,本质是一样的。如果用数学公式表示,那么:


ot=g(VSt)


St=f(Uxt+WSt−1)

将整个RNN过程总结成图4:t时刻的隐藏层S的值取决于输入向量X以及上一时刻(t-1)时的隐藏层St−1的值。

transformer cnn结合_seq2seq_04


图4

2.RNN的缺陷进而出现的其变种——LSTM

观察图3右侧,假设这个循环体需要很多次循环,或者说图3右侧的链条很长,那么RNN 会丧失学习到连接如此远的信息的能力(主要是因为反向传播计算参数时会出现梯度弥散和梯度爆炸,过长的链条会导致RNN无法对前后依赖间距过大的情况下失效)。举个简单的例子,男人爱女人,我们可以很简单的找到男人与女人间的联系,RNN可以很好的进行处理,因为它们距离很近,假设一篇文章(英文常作的完形天空),文章开头说了男主Alex是中国人,在中国长大,然后是一堆男主个人经历流水账,然而文章末尾一段中有一个空格,让你选择男主对哪个国家的文化最了解,正常情况下当然是“中国”,然而他们间隔太远了,RNN已经无法作出这样的判断,这就是RNN对长期依赖关系失效的例子。(在理论上,RNN 绝对可以处理这样的 长期依赖问题。可以选择良好的参数解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。)

由此,引出了RNN的变体——LSTM(长短期记忆模型)。

LSTM

从上一节中可以知道,传统RNN的结构如图5所示(为了清晰讲解LSTM,我这又换了一套字母表示,因为实在懒得自己画图了。。。见谅。。。)

transformer cnn结合_attention_05


图5

结合图5,详细看一下图5中每次循环的细节,如图6。图6中每个A方块就是图5左侧循环体中的某一次循环,或者说就是图5等号右侧中某个结构。图6中第一个A方块意味着第t-1次的输入是xt−1,输出是ht−1,然后到下一次循环,如前所述,第t次隐藏层的输出不仅仅与第t次的输入xt有关,还与上一次循环的输出ht−1有关,传统RNN经过第t-1次循环后,在第t次的循环中加入了一个tanh层(tanh层可以把一个值映射到一个(-1,1)之间的数)。

transformer cnn结合_seq2seq_06


图6

LSTM也有这种链状结构,不过其重复模块的结构不同。LSTM的重复模块中有4个神经网络层,并且他们之间的交互非常特别。如图7所示。

transformer cnn结合_attention_07


图7

图7展示了LSTM不同于普通RNN的内部结构,LSTM中(图7中中间部分)的核心也就是在这里,是这几个层的不同的功能,而整个这个结构,称作是cell state(姑且按照网络上最常见的翻译,翻译成细胞状态吧)。细胞状态类似于传送带。直接在整个链上运行,同时只有一些较小的线性交互。之前承载的信息可以很容易地流过而不改变。这个细胞状态其实就是“长期记忆”单元。

transformer cnn结合_seq2seq_08


图8

LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力(如图9所示)。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个pointwise乘法操作。



transformer cnn结合_rnn_09



图9

Sigmoid 层输出 0 到 1 之间的数值,描述每个部分有多少量可以通过。0 代表“不许任何量通过”,1 就指“允许任意量通过”。

LSTM 拥有三个门,来保护和控制细胞状态。(图7中的三个圈叉结构)

重点

LSTM的思想:

让我们思考一下我们RNN模型是如何更新它对目标的认识的。对于RNN,并未对其(隐藏层)更新过程施加任何限制措施,因此该认知过程可能十分混乱:比如拿上文中英文完形填空的例子,可能最后一段填空处前面十几个词与这个空填什么都没有关系,那么这种无规则,或者说无联系的模式会快速地改变并消失,模型很难保存长期记忆。因此,我们希望神经网络能学会如何更新自己的认知,换句话说“记住该记住的,忘记该忘记的”。RNN就是再对隐状态进行循环更新,LSTM也是这个过程,只是更新方式不同。

实现方法:

1.添加遗忘机制:遗忘机制也可以理解成记忆机制,这就像一天屠龙记里张三丰教张无忌太极剑那一段:“无忌,还记得多少”;“回师公,已经忘记一小半”;“现学现卖,也是难为你了,现在呢”;“已忘记一大半”;韦蝠王插嘴“不好,教主越忘越多”,张三丰:“那,现在呢?”“全忘了,忘的一干二净”,“不坏不坏,忘得真快。”然后张无忌裸装屌打对面神装AD,这里其实有一个思想,无关的东西会影响我们的记忆,或者说影响我们对事务的认知,因此需要“遗忘”机制,这个遗忘过程其实从另一个角度看也是“记忆”过程,忘记该忘记的,不就记住了该记住的么。

2.添加保存机制:对于新的输入,学习该输入信息的哪些内容具有价值,然后对这些有价值的信息存储到长期记忆中。因此当收到新的输入信息时,模型首先忘记所有它认为自己不再需要的长期信息。然后,再学习新输入信息的哪部分具有使用价值,并且将它们保存到长期记忆中。

3.将长期记忆聚焦为工作记忆:这里讲的工作记忆实际上就是图5中的ht。模型需要学习哪些长期记忆对目标应当发挥作用。例如,模型学习到了“我”是个中国人,而在讲述“另一个人”而非我时,不应当讲学习到的“中国人”与他联系到一起。因此,模型并不是始终都在使用全部的长期记忆的,它只需要学习哪些长期记忆对目标应当起作用。

这就是长短期记忆网络。LSTM相对于更新过程无序的RNN来讲,用遗忘、存储机制以及对长期记忆单元的是否激活来控制更新过程,更加精细,且解决了长程依赖问题。要知道,LSTM中解决长程依赖问题是一个默认,是一个基础功能。

接下来逐步讲解图7中这4个特别的层。

1.忘记层

忘记层,也可以称作忘记门,如图10所示。有前次工作记忆(隐藏层输出ht−1)与当前输入xt分别乘以权重矩阵(这里写的是一个权重矩阵Wf),加上偏置bf,然后使用sigmoid激活函数,得到一个元素属于 [0,1] 之间的输出。



transformer cnn结合_rnn_10



图10 第一层决定忘记哪些、忘记多少信息

接下来是确定应当将哪些新信息存放进细胞状Ct态中。包含两个部分:sigmoid 层称为“输入门层” 决定我们将要更新哪些值;然后,一个 tanh 层创建一个新的候选值向量C~t,tanh层的目的是计算可以从xt中学习的信息,也就是将长期记忆的候选添加记忆C~t。



transformer cnn结合_attention_11



图11 第二层确定更新的信息

在忘记我们认为不再需要的记忆并保存输入信息的有用部分后,我们就会得到更新后的长期记忆,如图12所示。用忘记门与前一次隐藏层的值相乘得到需要忘记的前次信息,再加上长期记忆的候选添加项乘需要更新的值得到新的候选值:



transformer cnn结合_transformer cnn结合_12



图12 更新细胞状态

最后,更新工作记忆(隐藏层),也就是如何将我们的长期记忆聚焦到能立刻发挥作用的信息上,确定输出是什么。对应于上面的第三个状态:将长期记忆聚焦为工作记忆。如图13所示。首先,运行一个sigmoid层来确定细胞状态的哪个部分将输出出去。接着,我们把细胞状态通过 tanh 进行处理(得到一个在 -1 到 1 之间的值)并将它和sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。



transformer cnn结合_attention_13



图13 输出信息

至此为止,标准的LSTM结构已经梳理完了。LSTM的整体图和细化流程如图14的左右所示。

transformer cnn结合_attention_14


图14

3.RNN的经典模式与变种

1.经典的RNN结构( 输入N维 vs 输出N维)

经典的RNN不需要过多解释,隐藏层的值由当前输入x1与上一次隐藏层的值h0。后面以此类推。如图15-图17所示。



transformer cnn结合_seq2seq_15



图15



transformer cnn结合_rnn_16



图16



transformer cnn结合_lstm_17



图17

每一次隐藏层循环的输出即用隐藏层值ht与权重矩阵相乘,然后进行softmax变换,如图18-19所示。最终,n维的输入对应于n维的输出。



transformer cnn结合_lstm_18



图18



transformer cnn结合_attention_19



图19

这种传统结构由于要求输入输出维度相同,所以很多情况下不试用,比如机器翻译,长度为10的中文句子翻译成英文程度几乎不可能是10。

2.输入N维 vs 输出1维

输入N维输出1维的结构如图20所示。只需要在循环最后一次的隐藏层进行对隐藏层值与权重矩阵相乘,加上偏置然后进行softmax操作即可。



transformer cnn结合_attention_20



图20

N vs 1的结构常用语分类问题,比如文本分类。

3.输入1维 vs 输出N维

这种结构有两种操作方式,与输入N维对输出1维类似,我们只在最初进入循环的时候给予输入值x,对于之后的循环不给予x。如图21所示。



transformer cnn结合_seq2seq_21



图21

第二种方式如图22(等价于图23)所示,对每次循环输入的都是那个x。

transformer cnn结合_lstm_22


图22

transformer cnn结合_seq2seq_23


图23

这种结构常用在生成内容的过程中,比如给定一个图像,生成对图像的描述。

4.Encoder-Decoder(编码解码模型),在文本领域也称作Seq2Seq模型

介绍前面几种结构,可能大家认为前面几种结构都不够普遍,还有一种最常用的结构,就是输入N维vs输出M维。这种模型也叫做Encoder-Decoder(编码解码模型),在文本领域也称作Seq2Seq模型,应用面很广,比如机器翻译,聊天机器人,语音识别等等领域。

首先,先要对输入内容进行编码,得到编码后的向量c,得到c的方式有多种,主要有以下3中:
-1.直接将隐藏层循环中最后一次循环得到的隐藏层值ht赋给c

-2.将隐藏层循环中最后一次循环得到的隐藏层值ht进行一定变换得到其映射g(ht)赋给c

-2.将隐藏层循环中每一次循环得到的隐藏层值hi进行一定变换得到其映射g(h1,h2,……,ht)赋给c

transformer cnn结合_attention_24


图24

然后用另一个RNN网络去解码c,有两种方式,第一种方式如图25所示,不再对解码的RNN进行输入的输入,而将c作为循环体的隐藏层初始值h0,进行循环;


transformer cnn结合_transformer cnn结合_25



图25 第二种方式如图26所示,将c作为解码RNN模型每个隐藏层的输入,进行循环。

transformer cnn结合_lstm_26


图26 其实seq2seq的结构和机制(即编码-解码模型)有些想自编码模型(AE-Auto-Encoder)中整体训练的过程(还有一种逐层预训练)。(关于AE和GAN如果之后有时间的话我也想详细介绍,毕业论文准备用一下。)以上即是seq2seq的简要概述。5.Attention机制attention,顾名思义,与“关注”、“注意力”有关,seq2seq是一个很优秀的模型,用在机器翻译,文档摘取,问答系统中可以有不错的效果,然而也存在一些弊病,编码和解码之间的唯一联系就是唯一的语义向量C。也就是说,编码器要将整个序列的信息压缩进一个固定长度的向量中去,首先,对于长的输入,语义信息很难完全包含在一个固定长度的向量C中,再一个,后输入的信息会覆盖、减弱先输入信息的重要性,导致对长文本的翻译以及其他应用大打折扣。因此出现了attention机制,如图27所示。attention机制的思想是:在产生输出的同时,还会产生一个“注意力范围”(表示为概率分布),以表示之后输出的时候要重点关注输入序列中的哪些部分(高概率的地方),然后根据关注的区域来产生下一个输出。接下来详细讲解一下。

transformer cnn结合_rnn_27


图27 attention机制中,编码器需要将输入的信息编码成一个向量的集合,在解码的时候,每次都会选择性的从向量序列中挑选一个子集进行进一步处理。在seq2seq中(比如图25的结构):假设输入是X=x1,x2,……,xm;输出是Y=y1,y2,……,yn,编码器将输入X编码为C,C=g(x1,x2,……,xm)。解码器根据句子X的中间语义C和之前已经生成的历史信息y1,y2,……,yi−1来生成i时刻要生成的单词yi,即: y1=f(C),…,yi=f(C,y1,y2,…,yi−1) 这个结构中,如果语句很长,语义向量C不能很好的涵盖语句的全部语义,那么输出的yi的质量就大打折扣。在attention机制下,如图27所示,目标句子中的每个单词都学会其对应的源语句子中单词的注意力分配概率信息(概率分布)。在生成每个单词yi的时候,原先都是相同的中间语义C会替换成根据当前生成单词而不断变化的Ci,即: y1=f(C1),…,yi=f(Ci,y1,y2,…,yi−1) 图27所示的attention机制中,我们用 aij衡量编码过程中第j阶段的隐藏状态值hj和解码时第i阶段的相关性,最终解码过程中第i阶段的输入的上下文语义信息 Ci=∑hjaij。以参考资料知乎中的例子进行展示吧:

transformer cnn结合_attention_28


图28 图28是机器翻译的过程,输入为“我 爱 中 国”4个字(其实个人更倾向于将他们表示成3个词——我,爱,中国),输出为I love China3个词,编码器中的h1 h4对应原句的4个字,第一个语义表示C1与h1关系最紧密,因此α11最大,即第1个输出在第1个输入上的关注度最大。以此类推,每个Ci对应的αij构成的向量就是概率分布,或者说语义信息关注的地方。最后,关于αij的计算:αij是从模型中学习出的,它和解码过程的第i-1阶段的隐状态、编码过程的第j个阶段的隐状态有关,即: eij=α(si−1,hj)
αij=softmax(eij)=exp(eij)∑exp(eik) 用图来说明一下,如图29所示,语义表示C3对应的α3j实际上由编码过程中每个隐藏状态的值hj与解码过程中第2阶段的隐藏状态值h2决定。

transformer cnn结合_attention_29


图29 这两个公式说的其实就是αij的值就是解码过程的第i−1阶段的隐状态、编码过程的第j个阶段的隐状态的某种组合然后求softmax将其每个元素映射到0~1,构成概率分布。(Tx是输入的维度)至此,本篇的全部内容就结束了!好累,可以休息了!