1.seq2seq的设计初衷
seq2seq设计的初衷是为了解决输入和输出都是不定长的问题,seq2seq使用encoder和decoder分别处理不定长的输入和输出,其示意图如下:
图中的C背景变量,编码了输入序列的信息,在输出的第一时刻,我们将初始的隐状态S0和初始输出y0(<BOS>)以及C作为输入,产生了y1和隐状态S1,下一时刻的输入为C,y1和S1。
2.seq2seq设计原理
①endocer部分
输入序列部分和普通的RNN没什么太大的区别,输入x可以直接使用索引,然后接一层嵌入层获取其向量,此时的嵌入层可以通过任务学习,也可以使用预训练的参数结果,或是使用预训练的参数再进行模型微调。
隐藏状态获取方式即:
关于背景向量C,有多种获取方式:
a.仅使用最后一个时间点的输出的隐藏变量
b.使用双向循环神经网络,将最后时刻的正序反序隐藏变量concatenete后的结果
c.使用attention机制
②decoder部分
decoder部分是为了生成序列,而我们希望根据encoder传来的信息后生成概率最大的某个序列,也就是希望最大化一个联合概率分布:
(t'代表输出decoder的时间戳)
这个联合概率是怎么构造的呢,其实就是遍历每一时刻,希望根据其前文和encoder部分的信息所产生的单词概率最大,我们将所有的条件概率乘起来,可以得到我们联合概率。
于是我们的损失函数就是最小化-log(联合概率):
下面我们希望知道如何使用函数p构造这个条件概率的连续乘积:
这里的p我们使用的是RNN,为什么这个p是RNN呢?,首先我们想要之前部分的信息,自然而然的就想到了RNN的t‘时刻的状态St’可以代表之前时刻的信息,然后我们还要融入C,于是就把这几个变量输入到RNN中去拟合函数了。
注意,最后对RNN的每一时刻的输出St'要使用softmax进行转换,使得其变为概率的形式。
p的问题解决了,Yt'-1是上一时刻的输出,C是背景变量也是已知的,St'怎么获得呢?
实际上,St'与上一时刻的输出,上一时刻的状态St'-1和C有关。
在初始化S0时,可以使用tanh(Wh1),h1是encoder反向的第一个单词向量。这是为了使得我们产生的第一个单词能够利用到encoder的第一个单词。
3.注意力机制
关于注意力机制的问题,归根到底是背景变量C的获取方式不同,在原始的C获取方式中,我们要把包含输入序列全部信息的C重复输入给decoder的每一时刻,而在真实的情况中,比如翻译的任务,我们希望decoder获取的C能够和encoder对应的几个单词高度相关,这就引出了注意力机制。
我们使用Ct'来代替之前简单的获取方式,它是encoder部分每个时刻隐藏变量的加权结果
权重获取方式:
权重由decoder上一时刻St'-1对encoder的每一时刻的隐藏变量ht做attention,这个attention是一个函数,其有多种表达方式:
如论文中有:
其中V,Ws,Wh皆为需要学习的参数,乘起来是我们需要的一个标量,然后过一个softmax获得对应权重。
说了这么多,这个函数g是如何获得的呢?
以GRU为例,实际上相当于把三者concatenate起来作为某一时刻的输入,但是重置门需要仅针对上一时刻的状态,其余与普通的GRU没有区别。