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是由\(N=6\)个独立的层堆叠而成的, 每层有两个子层:

  • 第一个层为multi-head self-attention结构
  • 第二层为simple, position-wise fully connected feed-forward network, 即基于位置的简单全连接反馈网络

在每个子层又引入了residual connection, 具体的做法为每个子层的输入与输出相加, 这就要求每个子层的输入与输出的维度是完全相等的. 然后再使用layer normalization. 因此每个子层的最终输出为:

\[LayerNorm(x + Sublayer(x))
\]

此外, 论文中限定了Embeding层的输出和两个子层的输入输出的维度都是\(d_{model}=512\).

Decoder

Decoder也是由\(N=6\)个独立的层堆叠而成的, 除了与Encoder层中的两个完全相同的子层外, 在两层之间又加入了一个multi-head attention, 这里是对Encoder的输出做attention处理.

与Encoder相同, 每个子层也引入了residual connection, 并且相加之后使用layer normalization得到每个子层最后的输出.

此外, 为了防止序列中元素的位置主导输出结果, 对Decoder层的multi-head self-attention层增加了mask操作, 并且结合对output embedding结果进行右移一位的操作, 保证了每个位置\(i\)的输出, 只会依赖于\(i\)位之前(不包括\(i\)位, 因为右移一位和mask).

Attention

论文中将常用的Attention结构从新的一种角度进行了描述:

Attention作为一种函数, 接受的输入为:

  • 一个query
  • 一组key-value pairs

即包含三部分, query, keysvalues. 三者都是向量.

输出就是对组中所有values的加权之和, 其中的权值是使用compatibility function(如内积), 对组内的每一个keysquery计算得到的.

例如, 对于常见的self-attention来说, 这里值的就是对于序列中的某一个元素对应的向量, 求得经过self-attention之后对应的向量. query指的是这个元素对应的向量(如NLP任务中句子序列中某一个单词对应的embedding向量), key-value pairs就是这个序列的所有元素, 其中的每个元素对应的key和value是完全相同的向量, 对于要比较的那个元素, 与query也是完全相同的. 然后使用当前向量和所有向量做内积得到权值, 最后的数据就是这个权值和对应向量的加权和.

论文中使用了两种Attention方法, 分别为Scaled Dot-Product AttentionMulti-Head Attention

Instead
.

Scaled Dot-Product Attention

我们假设querykey这两个用来比较的向量, 长度都为\(d_k\); value向量的长度为\(d_v\). 对query和所有keys进行点积得到值, 再对这里得到的每个点积结果除以\(\sqrt{d_k}\), 完成scale, 最后应用一个softmax function获得每个value对应的权值, 加权求得最后的输出向量.

这是对于一个query的情况. 实际中是直接对一个序列对应的所有querys直接进行计算, 将所有querys拼接成一个大的\(Q\)矩阵, 对应的keysvalues也拼接成\(K\)和\(V\)矩阵, 则Scaled Dot-Product Attention对应的计算公式为:

\[\text{Attention}(Q,K,V)=\text{softmax}(\frac{QK^T}{\sqrt{d_k}})V
\]

需要注意的点是: \(d_k\)较大时, 向量之间的点积结果可能就会非常大, 这回造成softmax函数陷入到梯度很小的区域. 为了应对这种情况, 适应了缩放因子\(\sqrt{d_k}\), 将点积结果尽量缩小到梯度敏感的区域内.

Multi-Head Attention

之前的方法都是对\(d_{model}\)维度的querys, keysvalues直接使用一个Attention函数, 得到结果, 在Multi-Head Attention方法中, 我们如下操作:

  • querys, keysvalues都分别进行\(h\)次的线性映射(类似于SVM中的线性核), 得到\(h\)组维度为分别为\(d_k\), \(d_k\), \(d_v\)的三种向量.

    需要注意的是, 这\(h\)次映射都是不同的映射, 每次线性映射使用的参数是不相同的, 而且这个映射是可学习的, 相当于得到了\(h\)个不同空间(虽然这些空间的维数是相等的)中的表征.

  • 然后并行的对这\(h\)组维度为分别为\(d_k\), \(d_k\), \(d_v\)的querys, keysvalues向量执行Attention函数, 每组都产生一个\(d_v\)维的输出结果.

  • 最后将这\(h\)个维度为\(d_k\)向量拼接起来.

  • 通过线性转换还原成\(d_{model}\)维度的向量.

公式表示为:

\[\text{MultiHead}(Q,K,V)=\text{Concat}(\text{head}_1, \cdots, \text{head}_h)W^O
\]

其中:

\[\text{head}_i=\text{Attention}(QW_i^Q,KW_i^K,VW_i^V)
\]

\(W_i^Q \in \mathbb{R}^{d_{model} \times d_k}\), \(W_i^K \in \mathbb{R}^{d_{model} \times d_k}\), \(W_i^V \in \mathbb{R}^{d_{model} \times d_v}\), 以及\(W_i^O \in \mathbb{R}^{hd_v \times d_{model}}\)都是可学习的线性映射参数. 在论文中超参数的选择为\(h=8\), 又由于\(d_{model}=512\), 因此\(d_k=d_v=d_{model}/h=64\).

因为中间计算的降维, 总体计算的消耗与直接使用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激活:

\[FFN(x) = \max(0, xW_1 + b_1)W_2 + b_2
\]

对于不同位置的线性变换是完全一样的, 即使用相同的参数.

这一层的输入输出都是\(d_{model}=512\), 中间隐层的维度为\(d_{ff}=2048\).

Embeddings and Softmax

使用已经训练好的embeddings将input token和output token转换成\(d_{model}\)维度的向量.

在最后Decoder的输出时, 将Decoder的输出通过一层线性变换层和一个softmax层, 转换成预测下一个token的概率向量. 这两个层中的参数也是提前训练好的.

在模型中, 两个embedding layers以及最后的softmax之前的线性变换, 这三者共享使用相同的矩阵权值.

对于embedding层, 里面的权值需要乘以\(\sqrt{d_{model}}\)之后再使用.

Positional Encoding

因为模型完全没有使用循环(RNN)和卷积(CNN), 而又想使用序列中的顺序信息, 就必须加入一些关于token相对位置绝对位置的信息. 因此我们加入Positional Encoding, 作为Encoder和Decoder的输入. 需要注意的是Positional Encoding产生的向量的维度为\(d_{model}\), 与原本的embedding向量维度相同, 从而两者可以被相加使用.

对位置进行embedding的方法很多, 有训练方法和指定方法, 本文中, 采用**频率不同的\(\sin\)和\(\cos\)函数:

\[PE_{pos,2i} = \sin(pos/10000^{2i/d_model})
\]
\[PE_{pos,2i+i} = \cos(pos/10000^{2i/d_model})
\]

其中\(pos\)代表位置, \(i\)代表第\(i\)维. 每个维度对应于不同频率不同的正弦函数. 使用这种方法, 我们认为能够反应相对位置中包含的信息, 这是因为: 对于一个固定的偏移量\(k\), \(PE_{pos+k}\)能表示成\(PE_{pos}\)的线性函数.

Why Self-Attention

之所以使用Self-Attention而没有使用循环或卷积的结构, 主要出于以下三点的考虑:

  • 每层的计算复杂度
  • 计算可以并行的程度
  • 对于序列问题, 长序列是一个难点. Self-Attention方法对于长短序列都有较好的表现. 这是由于我们认为在模型中, 前向后向传播的路径越短, 就更容易学习到其中的关系. 对于循环和卷积, 距离当前较远的位置, 在传播过程中都要经过较长的距离. 但对于Self-Attention结构, 无论两个元素在序列中的相对距离如何, 传播的距离总是相等的.

参考资料

[阅读笔记]Attention Is All You Need - Transformer结构的更多相关文章

  1. Hadoop阅读笔记(五)——重返Hadoop目录结构

    常言道:男人是视觉动物.我觉得不完全对,我的理解是范围再扩大点,不管男人女人都是视觉动物.某些场合(比如面试.初次见面等),别人没有那么多的闲暇时间听你诉说过往以塑立一个关于你的完整模型.所以,第一眼 ...

  2. 《JavaScript权威指南》第六版阅读笔记(二):JavaScript词法结构

    JavaScript使用Unicode字符集.ECMAScript3要求JS的实现必须支持Unicode 2.1及后续版本,ECMAScript 5要求JS的实现支持Unicode 3及后续版本. J ...

  3. 《Interest Rate Risk Modeling》阅读笔记——第三章:拟合期限结构

    目录 第三章:拟合期限结构 思维导图 扩展 第三章:拟合期限结构 思维导图 扩展 NS 模型的变种

  4. Hadoop阅读笔记(七)——代理模式

    关于Hadoop已经小记了六篇,<Hadoop实战>也已经翻完7章.仔细想想,这么好的一个框架,不能只是流于应用层面,跑跑数据排序.单表链接等,想得其精髓,还需深入内部. 按照<Ha ...

  5. ULMFiT 阅读笔记

    ULMFiT 阅读笔记 概述 这篇文章从文本分类模型入手,主要提出了两点:一是预训练语言模型在大中小规模的数据集中都能提升分类效果,在小规模数据集中效果尤为显著.二是提出了多种预训练的调参方法,包括D ...

  6. 论文阅读笔记 Improved Word Representation Learning with Sememes

    论文阅读笔记 Improved Word Representation Learning with Sememes 一句话概括本文工作 使用词汇资源--知网--来提升词嵌入的表征能力,并提出了三种基于 ...

  7. 论文阅读笔记“Attention-based Audio-Visual Fusion for Rubust Automatic Speech recognition”

    关于论文的阅读笔记 论文的题目是“Attention-based Audio-Visual Fusion for Rubust Automatic Speech recognition”,翻译成中文为 ...

  8. 《Graph Neural Networks: A Review of Methods and Applications》阅读笔记

    本文是对文献 <Graph Neural Networks: A Review of Methods and Applications> 的内容总结,详细内容请参照原文. 引言 大量的学习 ...

  9. 阅读笔记 1 火球 UML大战需求分析

    伴随着七天国庆的结束,紧张的学习生活也开始了,首先声明,阅读笔记随着我不断地阅读进度会慢慢更新,而不是一次性的写完,所以会重复的编辑.对于我选的这本   <火球 UML大战需求分析>,首先 ...

随机推荐

  1. SPFA算法详解

    前置知识:Bellman-Ford算法 前排提示:SPFA算法非常容易被卡出翔.所以如果不是图中有负权边,尽量使用Dijkstra!(Dijkstra算法不能能处理负权边,但SPFA能) 前排提示*2 ...

  2. Android自动化测试,5个必备的测试框架

    Appium Appium是一个开源的移动测试工具,支持iOS和Android,它可以用来测试任何类型的移动应用(原生.网络和混合).作为一个跨平台的工具,你可以在不同的平台上运行相同的测试.为了实现 ...

  3. element-ul二次封装table表格

    在项目中el的表格使用的地方太多了,若不进行封装,使用的时候页面会显得非常的冗余且难以维护,有时表格样式还不能做到一致:今天分享一个在工作中封装的表格 由于大多代码都在页面有介绍,就不在外面解释了 一 ...

  4. 招新裁老,两面派互联网大厂,培训三个月,就拿15K,凭什么?

    看到一位朋友在发帖子求问:亲身经历,(如有谎言我名字倒过来写)一个大学同学18年毕业的.在兰州一个二本学的兽医农牧,毕业难找工作,去深圳一个机构培训了三个月吧,然后就去做大数据 算法了,然后又去做ja ...

  5. activemq的搭建

    说在前面的话: 本节主要介绍activemq的介绍以及activemq的安装,希望可以给迷惑中的读者带来一丝灵感,activemq的安装是基于linux环境下的 准备的环境: 一台安装jdk的linu ...

  6. 我对Flutter的第一次失望

    老孟导读:此文翻译自:https://medium.com/@suragch/my-first-disappointment-with-flutter-5f6967ba78bf 我喜欢Flutter. ...

  7. webstorm编写vue、react 将大驼峰组件命名转换成短横杠命名

    大家好!我是木瓜太香,精通 webstorm 与常见前端技术的工程师,偶尔也在b站搞一些 webstorm 技巧教学,今天给大家带来的是大驼峰小驼峰快速转换短横杠命名或者下划线命名的方式. 开发中我们 ...

  8. 18_Python常用的模块中的某个方法

    1.imp模块==========>重新加载已加载过的模块方法 import imp imp.reload(mymod) # 重新加载已经加载过的mymod模块 2.ctypes模块====== ...

  9. 《闲扯Redis十一》Redis 有序集合对象底层实现

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  10. SpringBoot程序启动时在Oracle数据库中建表充值

    例子工程下载链接:https://files.cnblogs.com/files/xiandedanteng/gatling20200428-1.zip 需求:在工程启动时在Oracle数据库中建表. ...