【论文笔记copy】Attention总结三:self-attention与transformer
self-attention与transformer讲解
论文:attention is all you need.
参考
文章目录
1 self-attention具体
self-attention即K=V=Q。例如输入一个句子,那么里面的每个词都要和该句子中所有的词进行Attention计算。目的是学习句子内部的词依赖关系,捕获句子的内部结构。
1.1 过程
- 从每个endoer的输入向量创建三个向量
- 对每个单词,创建query, key, value。这些向量通过讲embedding * 训练得到的矩阵而来。
大部分的NLP中,Key和Value常常是同一个,即Key=Value。
- 新向量维度比embdding小,维度为64。这是一种架构选择,可以使multi-head attention计算大部分保持不变。
- query, key, value与计算分数
- 评分是通过query向量与评分的单词的key向量的点击来计算。
位置1单词的的分数就是dot(q1,k1), 第二个分数是dot(q1,k2)
-
将分数/8(论文中是key向量的维数(dk)的平方根,也就是sqrt(64))
为了得到更稳定的梯度。
-
softmax传递操作结果。
标准化,和为1.决定了每个单词在这个位置的表达量,很明显这个位置的单词有最高的softmax分数,但有时关注与当前单词相关的另一个单词是有用的。
-
每个value向量 * softmax分数
保持想要关注的词不变,去掉无关单词。
-
加权求和value向量。
将在此位置生成self-attention层的输出
得到的向量是可以发送到feed forward network的向量。实际中是用矩阵形式进行的,所以看看矩阵形式的self-attention。
1.2 矩阵的self-attention
过程:
- 计算query, key, value矩阵。
将embedding打包到矩阵X中,并乘以训练过的权重矩阵(WQ, WK, WV)。
X矩阵中的每一行对应于输入句子中的一个单词。
- 浓缩步骤2-6
1.3 Scaled Dot-Product Attention
以上过程中的:使用点积进行相似度计算的Attention就是Scaled Dot-Product Attention。只是多除了一个sqrt(dk)来起到调节作用,值得内积不至于太大。
2 transformer结构
总结:
- 编码器和解码器都使用了多头注意力机制(Multi-Head Attention)来学习文本的表示, 特别的这里Q=K=V,是自注意力机制(self-attention).
- 利用编码器和解码器Attention来进行翻译对齐,编码器输出的K和V以及解码器的输入Q作为Multi-Head Attention的输入
- 使用Positional Encoding来引入位置信息
- Masked Multi-Head Attention采用0-1mask消除右侧单词对当前单词的影响
- 残差网络连接和规范化(Add & Norm)使得深度网络更优化
2.1 Encoder与Multi-headed Attention
提高:
- 拓展了模型聚焦不同位置的能力。
- 赋予attention层多个“表示子空间”。
①有多个query\key\value权重矩阵集(transformer使用8个注意头,因此最终为每个encoder/decoder提供8个注意头集)
②每个集合都是随机初始化的。
③经过训练,每个集合用于将输入embeddings (or来自较低encoder/decoder的向量)投影到不同的表示子空间中。
2.1.1 multi-headed具体
在多头 attention的情况下,我们对每个头保持独立的Q/K/V权重矩阵,从而得到不同的Q/K/V矩阵。和之前一样,我们用X乘以WQ/WK/WV矩阵得到Q/K/V矩阵。
也是就:Queries, Keys, Values。
如果做上面列出的同样的self-attention计算,只是8次不同的加权矩阵,能得到8个不同的Z矩阵。
说的attention heads也就是产生的不同的Z矩阵。
前馈层不需要8个矩阵——它只需要一个矩阵(每个单词对应一个向量)。所以我们需要一种方法把这8个压缩成一个矩阵。
矩阵简化
- concatenate all the attention heads
- 乘以一个额外的权值矩阵W0。
- 得到结果Z矩阵,它能从所有attention heads里捕获到信息,从而把这个句子喂给FFNN
以上就是multi-headed self-attention。
以上过程:
如果可视化multi-headed,可以看到模型对target词的表达,在其他source word的一些表达中都有体现。
2.1.2 Positional Encoding 使用位置编码表示序列的顺序
目前为止,我们所描述的模型缺少的一件事是解释输入序列中单词顺序的方法。
transformer向每个输入的embedding添加一个向量——positional encoding。这些向量遵循模型学习的特定模式,这有助于确定每个单词的位置,或序列中不同单词之间的距离。
这里的直觉是,将这些值添加到embedding中,在embedding向量被投影到Q/K/V向量和点积attention期间,它们之间提供了有意义的距离。
如果我们假设embedding的维数是4,那么实际的位置编码应该是这样的:
位置编码向量的左半部分由一个函数(使用正弦)生成,右半部分由另一个函数(使用余弦)生成,连接起来后,就形成每个位置编码向量。
这种编码方法的优势是可以拓展到不可见的序列长度,比如如果我们的训练模型被要求翻译一个比训练集中任何一个句子都长的句子。
实际的位置编码示例:是embedding大小为20 * 512。它从中间一份为二。每一行对应一个向量的位置编码。
2.1.3 残差连接
需要在编码器体系结构中提到的一个细节是,每个编码器中的每个子层(self-attention, ffnn)周围都有一个残差连接,也就layer-normalization。
如图:
这也适用于解码器的子层。如果我们考虑一个由两个堆叠的编码器和解码器组成的Transformer,它应该如上。
2.2 Decoder部分
2.2.1 解码器具体
编码器会将顶层编码器的输出转换为一组attention向量K和v,分别由其“encoder-decoder attention”层中的各个解码器使用,过程见下动图:
以下步骤重复此过程,直到到达一个特殊符号,表示transformer解码器已完成其输出。
每一步的输出在下一个时间步中被提供给底层解码器,解码器就像编码器一样弹出解码结果。就像我们处理编码器输入一样,我们嵌入并添加位置编码到那些解码器输入中来表示每个单词的位置。
图2:https://jalammar.github.io/images/t/transformer_decoding_2.gif)
解码器中的self attention层的工作方式与编码器中的略有不同:
- 在decoder中,self-attention层只允许处理输出序列中较早的位置,这是通过在self-attention计算softmax(我猜是score的时候k不是all key)之前屏蔽将来的位置(将他们设置为-inf)来实现的!
- Encoder-Decoder Attention层的工作原理与multi-headed self attention类似,只是它从其下一层创建queries矩阵,并从编码器堆栈的输出中获取keys和values矩阵。
最后的Linear and Softmax层
解码器堆栈输出浮点数向量。我们怎么把它变成一个单词呢?这是最后一个线性层的工作,然后是一个Softmax层。
线性层是一个简单的全连接的神经网络,它将解码堆栈产生的向量投射到一个更大的向量上,称为logits向量。
这将使logits向量宽词典数量个单元格——每个单元格对应一个惟一单词的得分。这就是我们如何解释线性层之后的模型输出。
然后softmax层将这些分数转换为概率(所有为正,所有加起来等于1.0)。选择概率最高的单元格,并生成与之关联的单词作为这个时间步骤的输出。