暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

seq2seq是怎样的技术突破?遍地的attentiion又能如何?

克鲁斯卡 2021-10-29
571
大家好,好久不见。在之前的文章中和大家一起学习了循环神经网络RNN和长短期记忆网络LSTM,也提到了其中或多或少难以解决的一系列问题和相应的改进方法,那么随着技术的不断发展,后来又有了什么突破呢?本文就一起来看一下序列到序列模型(sequence to sequence,seq2seq)到底如何引起了新一轮的技术革命。

文章大纲


1. seq2seq介绍



可以说seq2seq是近几年最大的一个技术突破,其中的encoder-decoder结构也是现在大火的transformer的核心,attention机制更是“all you need”。
seq2seq在2014年由Google和Bengio的两篇文章提出,在当时对于解决机器翻译问题提出了相同的思路。

[1]Sutskever, Ilya, Oriol Vinyals, and Quoc V. Le. "Sequence to sequence learning with neural networks." *Advances in neural information processing systems*. 2014.


[2]Cho, Kyunghyun, et al. "Learning phrase representations using RNN encoder-decoder for statistical machine translation." *arXiv preprint arXiv:1406.1078* (2014).

机器翻译是一个many to many的问题,比如输入一段中文翻译为对应的英文,输入和输出的内容长度都大于1,而且具体多长也是不固定的。想象一下,做翻译的时候不能只是将一个单词翻译为另一个语种的单词,因为一些词会在翻译时消失,还有一些依赖于整段话的意思,所以翻译是一个句子级别的问题。如何使用深度学习来建模呢?传统的前馈神经网络和循环神经网络必须选择输入层和输出层的大小,但是因为many to many的问题,并不能为每个长度构建不同的网络,而seq2seq解决了这个问题。



2. seq2seq的内部结构





seq2seq模型主要包含两个部分,EncoderDecoder




2.1 encoder和decoder



输入一个序列,encoder相当于一个特征提取器,以隐藏状态向量的形式捕获输入序列的上下文信息,传输到解码器中,解码器会根据编码器中的向量和当前的输入解码出对应的输出序列。

这是宏观上来介绍seq2seq的模型结构,因为处理序列类型的任务,所以其内部的encoder和decoder可以使用LSTM或者其它的RNN模型,这部分可以参考之前的两篇文章RNNLSTM


假设使用simpleRNN作为内部结构,那么其中encoder向decoder传递的就是最后一个隐藏状态h,即为一个固定长度的向量,decoder在得到encoder的输入后,将该向量解码成输出序列


打开来看encoder和decoder的内部


上图encoder中的输入x是序列中的每个单词的词向量,经过计算得到一个隐藏状态h,h中累积了输入序列的信息,直到最后一个隐藏状态h中包含全部序列的信息, 将该状态输入到decoder。
decoder中的初始状态  就是刚才的最后一个隐藏状态,通过该状态就可以得到输入序列中的全部信息,然后one by one的得到输出序列。对解码器来说,第一个输入,也就是上图中的  始终是一个表示开始的词,可以用一个特殊字符替代,当然最后解码完成也会得到一个终止的特殊字符,这两个字符来控制解码。因为使用的是循环单元,所以每一个时间步都会通过上一个时间步的状态和当前的输入,计算得到的隐藏状态又会作为下一个时间步的输入,如此循环。



2.2 内部各层



在具体细分来讲,seq2seq模型的编码器有嵌入层和循环层,解码器有嵌入层、循环层和输出层

其中,嵌入层所做的都是将输入序列中的词转换为词向量,循环层都是通过参数矩阵和词向量的计算得到隐藏状态的传递,以此来捕获序列的整体信息,计算图如下

最后解码器中的输出层就是一个softmax函数转换,输出的是每个词的概率值,整体来看,解码器就是一个语言模型,来建模句子出现的概率。

来看一下上述分析的一个宏观过程

通过上面的介绍也可以看出来,基于RNN的seq2seq还是存在着对长序列的“遗忘”问题,并且随着序列的变长,网络层数也越来越深,也会出现梯度消失和梯度爆炸的问题。当然对于上述问题可以对encoder使用双向RNN来改进,这里不做过多的介绍,还有一种效果非常好的改进方式,那就是Attention——注意力机制


3. Attention



我们有时在生活或者学习中也会忘记一些东西,那么防止遗忘的方式就是重复,不断的回忆之前学过的知识,以此来达到记忆和加深理解的效果,所以将这个方法转移到解决RNN的问题上,通过Attention的名字大概也能猜到其核心思路,那就是不断的去回忆encoder中的语义信息,并且会特别注意某些词,这就使得处理长序列的问题可以避免信息损失,事实证明attention的效果非常好,以至于现在遍地都是attention。

[3]Bahdanau, D., Cho, K., and Bengio, Y., “Neural Machine Translation by Jointly Learning to Align and Translate”, <i>arXiv e-prints</i>, 2014.


[4]Luong, M.-T., Pham, H., and Manning, C. D., “Effective Approaches to Attention-based Neural Machine Translation”, <i>arXiv e-prints</i>, 2015.


对seq2seq来说,Attention机制就是在decoder每次输出预测的时候,会重复查看encoder中的隐藏状态,以此来避免遗忘信息。那么如何衡量每个词的重要程度,即要特别注意哪些词,这就需要给序列中的每个词分一个权重,这个权重的计算就需要encoder和decoder的隐藏状态,可以想象成一个函数f,函数的输入就是上面提到的隐藏状态。

上图中的α就是decoder在当前时间步对encoder中的隐藏状态的关注程度(隐藏状态包含了词的信息),也就是说,decoder每个时间步的关注点是不同的,这也符合常识,比如decoder中的当前输入是“吃”,那么就会更关注encoder中与食物有关的词。

这里因为decoder中每个时间步的状态不同,那么在与encoder中的所有状态做计算时,计算出的权重也就不同。


如下图,将中文翻译为英文的过程,在encoder中每个时间步对于权重的计算也不同,图中使用颜色的深浅表示

如何去计算这个权重α呢?





3.1 Attention的计算



在第一篇提出attention的论文中,其计算方法如下


这个和之前RNN那篇文章里的计算方法类似,将编码器中的隐藏状态h和解码器当前时间步的状态S做拼接,然后与参数矩阵w相乘,使用tanh激活函数,再与参数矩阵v相乘,得到的是一个实数 α ,再做一个softmax将数值映射到0,1之间。


之前说过transformer就是使用的attention,考虑到它的广泛性,这里介绍transformer中的计算方法

图中的描述很清楚,说明一下,  和  都是参数矩阵,都是要从训练中学习。至于qk代表了什么意思,这里可以先暂时理解为就是为了计算序列中词与词之间的相关性,进而得到权重,本篇先不深入讨论里面的计算意义,简单了解一下,在之后的关于transformer的文章中在深入剖析每一步的计算和其中的内在含义。


现在我们得到了每个隐状态h的权重,接下来要做的就是去“注意”。在未引入attention之前,decoder只是使用encoder中的最后一个状态来计算,现在则要注意全局状态,那就是用计算出来的权重和encoder中的所有隐藏状态作加权求和。


加权求和得到的C就是使用attention之后的上下文向量,这个向量中包含序列所有的信息,有了这个C就要去更新encoder的状态

使用attention之后,在计算当前时间步的状态就要考虑上下文向量C,如此也就捕获了需要关注哪些信息,更新状态  。需要注意的是,在更新完  后还要重新计算C,因为之前说过,每一个时间步的关注重点并不一样,所以每次都要重新计算权重信息,如此循环下去,直到终止符。


对这个过程的宏观可视化,也就是在传递给解码器的时候,是将编码器所有的隐藏状态都传递,而不仅仅是传递最后一个



4. self Attention




在了解了attention之后,让我们看一下有什么其它的改进方法,既然思想是让每一步注意到更相关的词,那不如直接在处理序列的时候就把序列中的各个词的相关性计算出来,这就是self attention。
[5]Cheng, J., Dong, L., and Lapata, M., “Long Short-Term Memory-Networks for Machine Reading”, arXiv e-prints, 2016.


self-attention提出于2016年,是一种将一个序列中的不同位置关联起来的以计算同一序列表示的注意力机制,按照刚才的例子,我们将attention用在单独的RNN上面。

隐藏状态  和向量  初始化为0向量,这里的  可以认为是  ,计算下一个隐藏状态  需要将当前输入  和context vector   拼接,然后与参数矩阵A相乘。


得到当前时间步的隐状态之后,同样的还是需要计算每个隐藏状态的权重,只不过这里就不需要decoder中的状态了,只考虑当前状态与其它状态的对比

如此循环下去,就可以得到整个序列中的各个词之间的关联度,到序列最后,信息的传递没有损失,因为每次都会利用权重得到各个词之间的相关性,也就是上下文向量每次都会回忆一遍序列的内容。



论文中的这个图也表现出,self attention能够学习当前单词与序列中前面的单词之间的相关性,红色代表当前输入的单词,蓝色的深浅代表权重大小。
现在介绍的不管是attention还是self attention都是基于RNN网络结构的,这里面还有一个非常大的问题,那就是循环神经网络虽然非常适合处理序列类型的数据,但是这种按序处理的特点限制了速度,每次都需要一步一步的向前传递信息。既然attention机制的特点是可以得到序列的全部信息,那为什么不丢掉RNN结构呢?这也是《Attention is all you need》这篇文章的一个创新点,丢掉RNN,并行处理,提高训练速度。

[6]Vaswani, A., “Attention Is All You Need”, <i>arXiv e-prints</i>, 2017.


总的来说,attention机制极大的提升了模型特征提取的能力,后来的Transformer也由此演变而来,前不久在CV领域的《Swin Transformer》也获得了ICCV的最佳论文,一方面是大势所趋,AI的各领域模型终会一统化,另一方面也证明了Transformer的生命力。

[7]Liu, Z., “Swin Transformer: Hierarchical Vision Transformer using Shifted Windows”, <i>arXiv e-prints</i>, 2021.

读到这里你可能对于attention机制的具体实现还是一头雾水,本文的目的也是初探attention,对注意力的大概思想了解一下,回顾一下技术发展的历程,到transformer的部分在深入讨论attention的具体实现。





以上便是本文的全部内容了,希望能给到你一点点的帮助


如果感觉还不错的话,感谢点赞和关注


分享知识,记录生活,一起进步🐐



Reference

https://dataxujing.github.io/seq2seqlearn/

https://towardsdatascience.com/day-1-2-attention-seq2seq-models-65df3f49e263

https://bgg.medium.com/seq2seq-pay-attention-to-self-attention-part-1-d332e85e9aad

Attention机制详解(一)——Seq2Seq中的Attention - 川陀学者的文章 - 知乎 https://zhuanlan.zhihu.com/p/47063917

https://github.com/wangshusen/DeepLearning/blob/master/Slides/9_RNN_9.pdf

http://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/




推荐阅读


1. 一文参透神经网络及其实现,揭开深度学习的神秘面纱

2. 一窥深度学习黑箱,拼接深层神经网络架构

3.  神经网络为何沉寂多年?一文体会深度学习的巨人之力——反向传播算法

4. 庖丁解牛看循环,图文并茂学原理,万字解析RNN——循环神经网络

5. LSTM是怎么改善SimpleRNN缺点,其作者又为何与主流学术圈分道扬镳?

点个在看你最好看


文章转载自克鲁斯卡,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论