Paper: Attention Is All You Need
Transformer
本文介绍了Transformer结构, 是一种encoder-decoder, 用来处理序列问题, 常用在NLP相关问题中. 与传统的专门处理序列问题的encoder-decoder相比, 有以下的特点:
结构完全不依赖于CNN和RNN
完全依赖于self-attention机制, 是一种堆叠的self-attention
使用全连接层
逐点point-wise计算的
整个Transformer的结构图如下所示:
Encoder and Decoder Stacks
如上所说, Transformer是基于stacked self-attention的, stack方式具体为:
Encoder
Encoder是由个独立的层堆叠而成的, 每层有两个子层:
第一个层为multi-head self-attention结构
第二层为simple, position-wise fully connected feed-forward network, 即基于位置的简单全连接反馈网络
在每个子层又引入了residual connection, 具体的做法为每个子层的输入与输出相加, 这就要求每个子层的输入与输出的维度是完全相等的. 然后再使用layer normalization. 因此每个子层的最终输出为:
此外, 论文中限定了Embeding层的输出和两个子层的输入输出的维度都是.
Decoder
Decoder也是由个独立的层堆叠而成的, 除了与Encoder层中的两个完全相同的子层外, 在两层之间又加入了一个multi-head attention, 这里是对Encoder的输出做attention处理.
与Encoder相同, 每个子层也引入了residual connection, 并且相加之后使用layer normalization得到每个子层最后的输出.
此外, 为了防止序列中元素的位置主导输出结果, 对Decoder层的multi-head self-attention层增加了mask操作, 并且结合对output embedding结果进行右移一位的操作, 保证了每个位置的输出, 只会依赖于位之前(不包括位, 因为右移一位和mask).
Attention
论文中将常用的Attention结构从新的一种角度进行了描述:
Attention作为一种函数, 接受的输入为:
一个query
一组key-value pairs
即包含三部分, query, keys和values. 三者都是向量.
输出就是对组中所有values的加权之和, 其中的权值是使用compatibility function(如内积), 对组内的每一个keys和query计算得到的.
例如, 对于常见的self-attention来说, 这里值的就是对于序列中的某一个元素对应的向量, 求得经过self-attention之后对应的向量. query指的是这个元素对应的向量(如NLP任务中句子序列中某一个单词对应的embedding向量), key-value pairs就是这个序列的所有元素, 其中的每个元素对应的key和value是完全相同的向量, 对于要比较的那个元素, 与query也是完全相同的. 然后使用当前向量和所有向量做内积得到权值, 最后的数据就是这个权值和对应向量的加权和.
论文中使用了两种Attention方法, 分别为Scaled Dot-Product Attention和Multi-Head Attention Instead.
Scaled Dot-Product Attention
我们假设query
和key
这两个用来比较的向量, 长度都为; value
向量的长度为. 对query
和所有keys
进行点积得到值, 再对这里得到的每个点积结果除以, 完成scale, 最后应用一个softmax function获得每个value
对应的权值, 加权求得最后的输出向量.
这是对于一个query
的情况. 实际中是直接对一个序列对应的所有querys
直接进行计算, 将所有querys
拼接成一个大的矩阵, 对应的keys
和values
也拼接成和矩阵, 则Scaled Dot-Product Attention对应的计算公式为:
需要注意的点是: 较大时, 向量之间的点积结果可能就会非常大, 这回造成softmax函数陷入到梯度很小的区域. 为了应对这种情况, 适应了缩放因子, 将点积结果尽量缩小到梯度敏感的区域内.
Multi-Head Attention
之前的方法都是对维度的querys
, keys
和values
直接使用一个Attention函数, 得到结果, 在Multi-Head Attention方法中, 我们如下操作:
对
querys
,keys
和values
都分别进行次的线性映射(类似于SVM中的线性核), 得到组维度为分别为, , 的三种向量.需要注意的是, 这次映射都是不同的映射, 每次线性映射使用的参数是不相同的, 而且这个映射是可学习的, 相当于得到了个不同空间(虽然这些空间的维数是相等的)中的表征.
然后并行的对这组维度为分别为, , 的
querys
,keys
和values
向量执行Attention函数, 每组都产生一个维的输出结果.最后将这个维度为向量拼接起来.
通过线性转换还原成维度的向量.
公式表示为:
其中:
, , , 以及都是可学习的线性映射参数. 在论文中超参数的选择为, 又由于, 因此.
因为中间计算的降维, 总体计算的消耗与直接使用Attention函数的消耗相近.
Transformer模型中Attention使用的特殊点
对于Multi-Head Attention, 在Transformer模型中有三个不同点:
在encoder-decoder attention层中, 即Encoder和Decoder两者之间的Attention中(对应于Decoder结构中的中间子层部分),
queries
来自于Decoder结构中上一个子层的输出. 这保证了对于Decoder中的每一个位置, 都能捕获input sequence各个位置的信息.Encoder中对应的是self-attention, 对应一个位置上的
query
,key
,value
是完全相同的一个向量. 每个位置的输出结果, 都会参考输入的所有位置.相似的, Decoder中第一个子层也是self-attention. 因此对于某个位置的元素, 会获取序列中所有序列的信息. 但为了防止leftward information flow(左侧信息泄露), 即防止出现自回归属性, 我们对这种Scaled Dot-Product Attention通过mask进行了限制, 屏蔽从第一个元素到当前元素(包含), 然后再进行Attention操作.
Position-wise Feed-Forward Networks
Encoder和Decoder都含有一个fully connected feed-forward network, 特殊的是, 这个网络分别对每个位置的attention层的输出向量单独地进行作用. 整个过程包含了两次线性变换以及中间夹杂的一次ReLU激活:
对于不同位置的线性变换是完全一样的, 即使用相同的参数.
这一层的输入输出都是, 中间隐层的维度为.
Embeddings and Softmax
使用已经训练好的embeddings将input token和output token转换成维度的向量.
在最后Decoder的输出时, 将Decoder的输出通过一层线性变换层和一个softmax层, 转换成预测下一个token的概率向量. 这两个层中的参数也是提前训练好的.
在模型中, 两个embedding layers以及最后的softmax之前的线性变换, 这三者共享使用相同的矩阵权值.
对于embedding层, 里面的权值需要乘以之后再使用.
Positional Encoding
因为模型完全没有使用循环(RNN)和卷积(CNN), 而又想使用序列中的顺序信息, 就必须加入一些关于token
的相对位置和绝对位置的信息. 因此我们加入Positional Encoding, 作为Encoder和Decoder的输入. 需要注意的是Positional Encoding产生的向量的维度为, 与原本的embedding向量维度相同, 从而两者可以被相加使用.
对位置进行embedding的方法很多, 有训练方法和指定方法, 本文中, 采用**频率不同的和函数:
其中代表位置, 代表第维. 每个维度对应于不同频率不同的正弦函数. 使用这种方法, 我们认为能够反应相对位置中包含的信息, 这是因为: 对于一个固定的偏移量, 能表示成的线性函数.
Why Self-Attention
之所以使用Self-Attention而没有使用循环或卷积的结构, 主要出于以下三点的考虑:
每层的计算复杂度
计算可以并行的程度
对于序列问题, 长序列是一个难点. Self-Attention方法对于长短序列都有较好的表现. 这是由于我们认为在模型中, 前向和后向传播的路径越短, 就更容易学习到其中的关系. 对于循环和卷积, 距离当前较远的位置, 在传播过程中都要经过较长的距离. 但对于Self-Attention结构, 无论两个元素在序列中的相对距离如何, 传播的距离总是相等的.
参考资料
最后更新于
这有帮助吗?