Transformer模型
【Transformer系列】Transformer模型与代码详解 - 知乎
RNN的局限性
采用Attention机制的原因是考虑到RNN(或者LSTM,GRU等)的计算限制为是顺序的,也就是说RNN相关算法只能从左向右依次计算或者从右向左依次计算,这种机制带来了两个问题:
- 时间片的计算依赖时刻的计算结果,这样限制了模型的并行能力;
- 顺序计算的过程中信息会丢失,尽管LSTM等门机制的结构一定程度上缓解了长期依赖的问题,但是对于特别长期的依赖现象,LSTM依旧无能为力。
Transformer的提出解决了上面两个问题,首先它使用了Attention机制,将序列中的任意两个位置之间的距离是缩小为一个常量;其次它不是类似RNN的顺序结构,因此具有更好的并行性,符合现有的GPU框架。
Encoder-Decoder结构
首先,编码(encode)由一个编码器将输入序列转化成一个固定维度的稠密向量,解码(decode)阶段将这个激活状态生成目标译文。
结构特点
- 不论输入和输出的长度是什么,中间的“向量c”长度都是固定的(这是它的缺陷所在)。
- 根据不同的任务可以选择不同的编码器和解码器(例如,CNN、RNN、LSTM、GRU等)
- Encoder-Decoder的一个显著特征就是:它是一个end-to-end的学习算法。
信息丢失的问题
编码器和解码器之间有一个共享的向量c,来传递信息,而且它的长度是固定的。这会产生一个信息丢失的问题,也就是说,编码器要将整个序列的信息压缩进一个固定长度的向量中去。但是这样做有两个弊端
- 语义向量无法完全表示整个序列的信息,
- 还有就是先输入的内容携带的信息会被后输入的信息稀释掉,或者说,被覆盖了。输入序列越长,这个现象就越严重。
这就使得在解码的时候一开始就没有获得输入序列足够的信息,那么解码的准确度自然也就要打个折扣了。
为了解决这些缺陷,随后又引入了Attention机制以及Bi-directional encoder layer等。Attention模型的特点是Encoder不再将整个输入序列编码为固定长度的中间向量,而是编码成一个【向量序列】。这样,在产生每一个输出的时候,都能够做到充分利用输入序列携带的信息。
Seq2Seq模型
equence在这里可以理解为一个字符串序列,当我们在给定一个字符串序列后,希望得到与之对应的另一个字符串序列(如 翻译后的、如语义上对应的)时,这个任务就可以称为Sequence2Sequence了。*这种结构最重要的地方在于输入序列和输出序列的长度是可变的。
Encoder-Decoder强调的是模型设计(编码-解码的一个过程),Seq2Seq强调的是任务类型(序列到序列的问题)。
Attention 机制
Attention 的3大优点
之所以要引入 Attention 机制,主要是3个原因:
Attention 原理的3步分解:
第一步: query 和 key 进行相似度计算,得到权值
第二步:将权值进行归一化,得到直接可用的权重
第三步:将权重和 value 进行加权求和
multi-head attention
多头Attention,这是Attention is All You Need中提到的multi-head attention,用到了多个query对一段原文进行了多次attention,每个query都关注到原文的不同部分,相当于重复做多次单层attention
CNN+Attention
CNN上加Attention可以加在这几方面:
a. 在卷积操作前做attention,比如Attention-Based BCNN-1,这个任务是文本蕴含任务需要处理两段文本,同时对两段输入的序列向量进行attention,计算出特征向量,再拼接到原始向量中,作为卷积层的输入。
b. 在卷积操作后做attention,比如Attention-Based BCNN-2,对两段文本的卷积层的输出做attention,作为pooling层的输入。
c. 在pooling层做attention,代替max pooling。比如Attention pooling,首先我们用LSTM学到一个比较好的句向量,作为query,然后用CNN先学习到一个特征矩阵作为key,再用query对key产生权重,进行attention,得到最后的句向量。
Transformer结构
完整结构如下
Transformer的本质上是一个Encoder-Decoder的结构
编码器由6个编码block组成,同样解码器是6个解码block组成。与所有的生成模型相同的是,编码器的输出会作为解码器的输入
输入编码模块
在最底层的block中, 将直接作为Transformer的输入,而在其他层中,输入则是上一个block的输出。
self-attention模块
Self-Attention是Transformer最核心的内容
在Transformer的encoder中,数据首先会经过一个叫做‘self-attention’的模块得到一个加权之后的特征向量
Attention的计算方法
整个过程可以分成7步:
- 将输入单词转化成嵌入向量;
- 根据嵌入向量得到 q,k,v三个向量;
- 为每个向量计算一个score:q×k 具体探索方法就是两者进行点积,某种意义上就是求解余弦相似度,如果两者相似度较高,则赋予较大的值Score来反应两者的关系。
- 为了梯度的稳定,Transformer使用了score归一化,即除以根号d
- 对score施以softmax激活函数;
- softmax点乘Value值 ,得到加权的每个输入向量的评分
- 相加之后得到最终的输出结果
实际计算过程中是采用基于矩阵的计算方式
采用残差结构
自注意力和前馈网络中均包含残差连接(目的是为了防止梯度消失,提高训练稳定性)
Multi-Head Attention
Multi-Head Attention相当于多个不同的self-attention的集成。Multi-Head Attention的输出分成3步:
- 将数据分别输入到8个self-attention中,得到8个加权后的特征矩阵 。
- 将8个按列拼成一个大的特征矩阵;
- 特征矩阵经过一层全连接后得到输出
由于在机器翻译中,解码过程是一个顺序操作的过程,也就是当解码第 个特征向量时,我们只能看到第 及其之前的解码结果,论文中把这种情况下的multi-head attention叫做masked multi-head attention。
因为,相比单头自注意力,多头的优势主要体现在:
- 更好的建模能力:利用多个注意力头可以捕获序列中更多的信息和特征,从而提升模型的建模能力。
- 更好的泛化能力:多头自注意力可以提高模型对新数据的泛化能力,因为它可以将不同方面的特征编码到不同的注意力头中,从而使模型更加全面地理解输入序列。那么多头是如何实现的呢?
Feed Forward Neural Network
前馈网络
self attention特征向量会被送到encoder的下一个模块,即Feed Forward Neural Network。这个全连接有两层,第一层的激活函数是ReLU,第二层是一个线性激活函数,可以表示为:
Encoder-Decoder Attention
在解码器中,Transformer block比编码器中多了个encoder-cecoder attention。在encoder-decoder attention中,Q来自于解码器的上一个输出, K和 V则来自于与编码器的输出。其计算方式完全和图前面的过程相同。
由于在机器翻译中,解码过程是一个顺序操作的过程,也就是当解码第 k个特征向量时,我们只能看到第 及其之前的解码结果,论文中把这种情况下的multi-head attention叫做masked multi-head attention。
Decoder的结构如图所示,它和encoder的不同之处在于Decoder多了一个Encoder-Decoder Attention,两个Attention分别用于计算输入和输出的权值:
- Self-Attention:当前翻译和已经翻译的前文之间的关系;
- Encoder-Decnoder Attention:当前翻译和编码的特征向量之间的关系。
再仔细一看,这个编码-解码注意力的k和v值为enc,其实也就是编码器的输出。也就是说,每层解码层的输入不光有上一解码层的输出(dec),还有编码器的最终输出(enc)唯一区别仅在输入的来源
位置编码
我们介绍的Transformer模型并没有捕捉顺序序列的能力,也就是说无论句子的结构怎么打乱,Transformer都会得到类似的结果。换句话说,Transformer只是一个功能更强大的词袋模型而已。
为了解决这个问题,论文中在编码词向量时引入了位置编码(Position Embedding)的特征。具体地说,位置编码会在词向量中加入了单词的位置信息,这样Transformer就能区分不同位置的单词了。
常见的编码模式有:a. 根据数据学习;b. 自己设计编码规则。
通常位置编码是一个长度为 d(model)的特征向量,这样便于和词向量进行单位加的操作
编码公式如下:pos 表示单词的位置, i表示单词的维度。