- 最近
transformer
的结构改进论文挺多的,总结一下。 -
transformer
是一个seq2seq
模型。
从RNN谈起
-
缺点:不能处理过长的句子。
-
LSTM
可以一定程度上缓解这个问题,因为他有记忆单元,以及可以选择什么时候进行遗忘的门控机制,但是还是不能处理过长句子中的依赖问题(大约能记住30-40
个词之间的依赖关系,普通的RNN
只能记住5-6
个词的依赖关系)。 -
RNN-based model
还有一个问题就是encoder
的时候不能并行,可以从上面的图中看到,只有当单词x0
处理完成了以后,才能处理单词x1
。
attention 机制
- 为了解决长时间长序列之间的单词依赖问题,引入了
attention
机制,就是在处理句子的时候,不再是一个句子处理完成以后只取最后一个hidden state
当做句子的表示丢给decoder
,而是每个时刻的hidden state
,decoder
都可以按其所需对hidden state
进行加权访问。
- 可以看到之前的
seq2seq
模型decoder
的时候只获取了encoder
的最后一个状态,加入了attention
机制以后就可以获取每一个时间步的信息了。
CNN-based model
- 可以想到
CNN
还是可以解决RNN
的不足的,因为首先CNN
本来就是并行做卷积的因此速度encode
速度比RNN
快的多,其次CNN可以通过卷积核捕获短期依赖,然后通过叠加层数捕获长期依赖。比如下面的wavenet
的处理方式。
- 既然
CNN
和Attention
机制这么好,那么把两者结合起来岂不是天下无敌?是的这就是Transfomer
Transformers
-
Transformers
中用的是self-attention
-
首先我们看一下
transfomer
的整体架构,也是seq2seq
模型,普通的transfomer
叠了6
层,而big transfomer
叠了12
层。
-
每一个
encoder
都是由两部分组成的,self-attention
帮助句子中的每个单词建立依赖关系,而且仅仅是使用self-attention
来建立联系的,而feed-forward
层是每一个token
都是单独向前的(就是一个非线性层),因此不捕获token
之间的依赖关系,同时不同token
的feed forward
可以并行。
-
decoder
还有一个多于的attention
层,帮助decoder
集中于输入句子中的特定的部分。
self-attention
- 根据三个不同的矩阵得到,
q,k,v
。(当然有一种self-attention
是不乘矩阵的直接对embedding
的矩阵进行操作,self-attention
得到的是embedding * embedding转置* embedding
,这样的好处是效果不错也没有额外的参数 ) -
self-attention
的实现方式。
multi-head attention
-
linear
层其实就是一个大矩阵,embedding matrix
的维度是seqLen*embedding dim
,而K,Q,V
对应的W
矩阵(Wk,Wq,Wv)
的size
都是embedding dim * hidden size
那么KQV
矩阵的size
是seqLen * hidden size
。multi-head attention
和原始的attention
的区别是,原始的attention
只有一组W
矩阵,现在的multi-head attention
是有多组,常用的设置是将hidden size
设置为原来的1/n
,比如原来的hidden size
是512
维,有8
个head
那么现在就有8
组W
矩阵各自的hiddensize
是64
,这样QKV
矩阵的维度是64* 512
(原来是512*512
)但是得到的Z
尺寸还是一样的依然是seqLen*512
,然后将8
个Z concat
起来过一个linear
(就是乘以一个4096*512
的矩阵)得到seqlen*512
的最终的state
。(那个hidden state
变成1/n
也不一定是效果最好的,你可以设置成其他值) - 这个操作和
CNN
里面使用多个卷积核是一样一样的。
- 可以看到不同的
head
注意到不同的位置,相当于不同卷积核捕获不同的特征。
表示序列的位置信息使用Positional Encoding
- 因为仅仅使用
self-attention
的话就相当于是一个词袋模型,所以我们需要引入表示位置信息的编码。
- 看到源代码里面
positional encoding
实现方式,是一个比较复杂的三角函数,naacl18
上有一篇文章论文使用了相对位置的positional encoding
效果提升了0.6
个bleu
,总之这个positional encoding
是一个比较ugly
的东西,大家都想改进他,但是却苦于没有好的方法。
Transformer中的残差连接
- 在
encoder
的每个sub layer
之间(一个self-attention
或者一个feed forward
算一个sublayer
)是有残差连接的,他们大概长这样
- 所谓的残差连接实现的时候只不过是把原来的
x1
保存下来,然后做layernorm
的时候和下面模块中传递进来的z
加起来即可。
- 在
decoder
中同样也有残差连接
decoder部分
-
encoder
的输入是单词的embedding
,输出是一组attention
的K
矩阵和V
矩阵,这样decoder
可以用到这个attention
矩阵就可以更好的获取输入句子信息。(embedding matrix
各自乘以一个矩阵得到K
和V
)
- 可以看到
decoder
的时候,也是一个时间步一个时间步运行的,因此decoder
的时候没有加速的(还是自回归模型,现在比较活的非自回归模型就是解决这个问题的,但是效果还是不能比),而encoder
的时候是并行的,K
和V
矩阵是最终6
层以后得到的embedding
各自乘以一个矩阵K
和V
- 值得注意的是
decoder
中的self-attention
机制和是不同的,因为生成新的单词的时候只能看到前面已经生成过单词的信息,因此需要用mask
挡住后面的位置(设置为-inf
) -
encoder-decoder attention
层的work
方式和multihead self-attention
方式是很像的,只不过使用的Queries
矩阵来自下面层的输入,而Keys
和Values Matrix
用的是的encoder
产生的。 - 最后的
softmax
层:
网友评论