首先我们来了解一下Encoder-Decoder 模型, Encoder-Decoder 主要是 NLP 领域里的概念,它并不特值某种具体的算法,而是一类算法的统称,称之为Encoder-Decoder结构更合适。Encoder-Decoder 算是一个通用的框架,在这个框架下可以使用不同的算法来解决不同的任务。Encoder-Decoder 这个框架很好的诠释了机器学习的核心思路:
将现实问题转化为数学问题,通过求解数学问题,从而解决现实问题。
Encoder 又称作编码器。它的作用就是“将现实问题转化为数学问题”:
Decoder 又称作解码器,他的作用是“求解数学问题,并转化为现实世界的解决方案”:
把两个环节连接起来,用通用的图来表达则是下面的样子:
关于 Encoder-Decoder,有两点需要说明:
只要是符合上面的框架,都可以统称为 Encoder-Decoder 模型。具体实现 Encoder-Decoder 的时候,编码器和解码器都不是固定的,可选的有CNN/RNN/BiRNN/GRU/LSTM等等,你可以自由组合。比如说,你在编码时使用BiRNN,解码时使用RNN,或者在编码时使用RNN,解码时使用LSTM等等。当然提到 Encoder-Decoder 模型就经常提到一个名词——Seq2Seq。其实Encoder-Decoder和Seq2Seq几乎就是等价的,只不过Encoder-Decoder是一种抽象的框架概念,Seq2Seq是具体的一种实现。
首先要知道为什么会提出 Seq2Seq模型,它是处理序列到序列问题的利器。传统的循环神经网络中是将一个序列转化成定长输出
。而 Seq2Seq 可以将一个序列转化成一个不定长的序列输出(如机器翻译中,源语言和目标语言的句子往往并没有相同的长度)。
(1)从单层网络谈起
首先来了解一下最基本的单层网络,它的结构如图:
输入是x
,经过变换Wx+b
和激活函数f
得到输出y
。
(2)经典的RNN结构(N vs N)
在实际应用中,我们还会遇到很多序列形的数据:
如:
序列形的数据就不太好用原始的神经网络处理了。为了建模序列问题,RNN引入了隐状态h(hidden state)
的概念,h可以对序列形的数据提取特征,接着再转换为输出。先从h1的计算开始看:
一个箭头就表示对该向量做一次变换
。如上图中h0和x1分别有一个箭头连接,就表示对h0和x1各做了一次变换。在很多论文中也会出现类似的记号,初学的时候很容易搞乱,但只要把握住以上两点,就可以比较轻松地理解图示背后的含义。
h2的计算和h1类似。要注意的是,在计算时,每一步使用的参数U、W、b都是一样的,也就是说每个步骤的参数都是共享的
,这是RNN的重要特点,一定要牢记。
依次计算剩下来的h3、h4(使用相同的参数U、W、b):
我们这里为了方便起见,只画出序列长度为4的情况,实际上,这个计算过程可以无限地持续下去。
目前我们的RNN还没有输出,得到输出值的方法就是直接通过h进行计算。正如之前所说,一个箭头就表示对对应的向量做一次类似于f(Wx+b)的变换,这里的这个箭头就表示对h1进行一次变换,得到输出y1:
剩下的输出类似进行(使用和y1同样的参数V和c):
OK!大功告成!这种输入序列长度为N且输出序列长度也为N的RNN就是最经典的RNN结构
,我们像搭积木一样把它搭好了。它的输入是x1, x2, …xn,输出为y1, y2, …yn,也就是说,输入和输出序列必须要是等长的
。
由于这个限制的存在,经典RNN的适用范围比较小,但也有一些问题适合用经典的RNN结构建模,如:
(3)N VS 1
有的时候,我们要处理的问题输入是一个序列,输出是一个单独的值而不是序列,应该怎样建模呢?实际上,我们只在最后一个h上进行输出变换就可以了:
这种结构通常用来处理序列分类问题。如输入一段文字判别它所属的类别,输入一个句子判断其情感倾向,输入一段视频并判断它的类别等等。
(4)1 VS N
输入不是序列而输出为序列的情况怎么处理?我们可以只在序列开始进行输入计算:
还有一种结构是把输入信息X作为每个阶段的输入(右图省略了一些X的圆圈,是一个等价表示):
这种1 VS N的结构可以处理的问题有:
(5)N vs M
下面我们来介绍RNN最重要的一个变种:N vs M。这种结构又叫Encoder-Decoder模型,也可以称之为Seq2Seq模型。
原始的N vs N RNN要求序列等长,然而我们遇到的大部分问题序列都是不等长的,如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。
为此,Encoder-Decoder结构先将输入数据编码成一个上下文向量c(context vector):
得到c有多种方式,最简单的方法就是把Encoder的最后一个隐状态赋值给c,还可以对最后的隐状态做一个变换得到c,也可以对所有的隐状态做变换,可以表示为下面三种方式:
拿到c之后,就用另一个RNN网络对其进行解码,这部分RNN网络被称为Decoder。具体做法就是将c当做之前的初始状态h0输入到Decoder中:
还有一种做法是将c当做每一步的输入:
Decoder是Encoder的逆过程,每个状态由之前的状态和context vector决定
,即:
h i ′ = f ( c , h 1 ′ , h 2 ′ , . . . , h i − 1 ′ ) h_i^{'}=f(c, h_1^{'}, h_2^{'},...,h_{i-1}^{'}) hi′=f(c,h1′,h2′,...,hi−1′)
y i = g ( h i ′ ) y_i=g(h_i^{'}) yi=g(hi′)
由于这种Encoder-Decoder结构不限制输入和输出的序列长度,因此应用的范围非常广泛,比如:
上面提到:Encoder 和 Decoder 之间只有一个「向量 C」来传递信息,且 C 的长度固定。这样做有两个弊端:
针对信息丢失这个问题,后面提出了 Seq2Seq+Attention 的模型。
最初Seq2Seq的Encoder和Decoder都是基于RNN的,但是传统的基于 RNN 的 Seq2Seq 模型不能并行计算,效率低。针对这个问题,后来提出了基于CNN的Seq2Seq 模型。
FaceBook提出了由CNN构成的Seq2Seq模型,完全采用堆叠的CNN来构建encoder和decoder,通过CNN的堆叠方式来回溯sequence中long-range dependencies关系,在decoder端采用了多层的attention机制(提出CNN+Seq2Seq的时候就引入了Attention机制)。堆叠CNN之间采用加入残差的GLU单元来连接,加快计算的同时最大限度保留输入sequence的信息。下面的【3.2】节会介绍更多内容。
Attention 机制的提出就是为了解决「序列过长,信息丢失」
的问题。原理详见Attention机制详解。
由于传统的基于RNN的Seq2Seq存在的序列过长,信息丢失的问题,后来提出了基于RNN的Seq2Seq+Attention模型,在decoder端,采用含一个隐含层的前向网络,采用自适应(adaptive)的方法来计算观测序列X中,每个word与输出标签Y的权重。
优点是可以自适应地计算一个权值矩阵W,权重矩阵W长度与X的的词数目一致,每个权重衡量输入序列X中每个词对输入序列Y的重要程度,不需要考虑输入序列X与输出序列Y中,词与词之间的距离关系。缺点还是和RNN一样,LSTM依赖t-1的历史信息来计算t时刻的信息,因此不能并行实现,计算效率比较低,特别是训练样本量非常大的时候。
基于 CNN 的 Seq2Seq 模型提出来的时候超越了谷歌创造的基于LSTM机器翻译的效果。重要原因在于采用了很多的窍门,这些技巧值得学习:
捕获long-distance依赖关系
单层CNN的问题是难解决长依赖的序列, 解决办法是叠加多层的CNN。底层的CNN捕捉相聚较近的词之间的依赖关系,高层CNN捕捉较远词之间的依赖关系。通过层次化的结构,实现了类似RNN(LSTM)捕捉长度在20个词以上的Sequence的依赖关系的功能。
效率高
假设一个sequence序列长度为n,采用RNN(LSTM)对其进行建模 需要进行n次操作,时间复杂度O(n)。相比,采用层叠CNN只需要进行n/k次操作,时间复杂度O(n/k),k为卷积窗口大小。
并行化实现
RNN对sequence的建模依赖于序列的历史信息,因此不能并行实现。相比,层叠CNN对整个sequence进行卷积,不依赖序列历史信息,可以并行实现,特别是在工业生产,面临处理大数据量和实时要求比较高的情况下,模型训练更快。
融合多层attention
融合了Residual connection、liner mapping的多层attention。通过attention决定输入的哪些信息是重要的,并逐步往下传递。把encoder的输出和decoder的输出做点乘(dot products),再归一化,再乘以encoder的输入X之后做为权重化后的结果加入到decoder中预测目标语言序列。
gate mechanism
采用GLU做为gate mechanism。GLU单元激活方式如下公式所示:
f ( X ) = ( X ∗ W + b ) + O ( X ∗ V + c ) f(X)=(X*W+b)+O(X*V+c) f(X)=(X∗W+b)+O(X∗V+c)
进行了梯度裁剪和精细的权重初始化,加速模型训练和收敛
在CNN和RNN用于NLP问题时,CNN也是可行的,且网络结构搭建更加灵活,效率高,由于RNN训练时往往需要前一时刻的状态,很难并行,特别是在大数据集上,CNN-Seq2Seq往往能取得比RNN-Seq2Seq更好的效果。
基于CNN的Seq2Seq模型除了具有基于RNN的Seq2Seq模型捕捉long distance dependency的能力,此外,最大的优点是速度快,效率高,可以并行化实现,效率比基于RNN的Seq2Seq模型高。缺点非常占内存,并且计算量与观测序列X和输出序列Y的长度成正比。参数太多,里面有很多的trick,大数据量上参数调整并不容易。
针对基于CNN和RNN的Seq2Seq模型存在的不足,《Attention is all you need》这篇论文提出了一种完全基于Attention Mechanism(Self Attention)的Transformer
架构:抛弃CNN和RNN,基于Attention来构造Encoder和Decoder,搭建完全基于Attention
的Seq2Seq模型
。论文的详细阅读笔记:Transformer 模型详解。
参考:
【1】 完全图解RNN、RNN变体、Seq2Seq、Attention机制
【2】 一文看懂 NLP 里的模型框架 Encoder-Decoder 和 Seq2Seq
【3】 机器翻译不可不知的 Seq2Seq 模型
【4】模型汇总16 各类Seq2Seq模型对比及《Attention Is All You Need》中技术详解