Attention Is All You Need (Transformer) - 论文精读学习笔记

Cook 2024.08

You are what you eat.
And I'm cooking what I eat!
:)

More food...🍜

目录

提前说明:本系列博文主要是对参考博文的解读与重述(对重点信息进行标记、或者整段摘录加深自己的记忆和理解、融合多个博文的精髓、统合不同的代表性的案例),仅做学习记录笔记使用。与君共享,希望一同进步。

 

简介:《Attention Is All You Need》是一篇由Google DeepMind团队在2017年发表的论文,该论文提出了一种新的神经网络模型,称为Transformer模型,用于自然语言处理任务。

Transformer和Attention(注意力机制)的关系就是这样的!

优势:对序列进行更好地建模。

 

补充 它是主要用来解决RNN系列在在处理长序列数据时存在一些问题,比如难以并行计算和难以捕捉长距离依赖关系,而Transformer模型则通过引入自注意力机制(Self-Attention)来解决这些问题。

 

补充 该论文还提出了一种新的训练方法,称为“无序列信息的训练(Training without sequence information)”,其基本思想是将输入序列中的每个位置看作独立的词向量,而不考虑它们在序列中的位置信息。通过这种方式,可以避免序列中的位置信息对模型训练的影响,提高模型的泛化性能。

 

中译英:机器翻译


输入:简将访问非洲

输出(参考基准):

输出(算法模型):

Jane visits the Africa.

BLEU Score:利用参考输出和算法输出计算得到。

 

背景知识

早期的处理:

在深度学习时代早期,人们使用RNN(循环神经网络)来处理机器翻译任务。一段输入先是会被预处理成一个token序列。

预处理
输入
token序列
token序列:包含很多token的序列

RNN会对每个token逐个做计算,并维护一个表示整段文字整体信息的状态。根据当前时刻的状态,RNN可以输出当前时刻的一个token。

所谓token,既可以是一个单词一个汉字,也可能是一个表示空白字符、未知字符、句首字符特殊字符

输入:

 

这种简单的RNN架构仅适用于输入和输出等长的任务。然而,大多数情况下,机器翻译的输出和输入都不是等长的。

 

改进
改进
改进
简单架构
RNN架构
缺点:这种简单的RNN架构仅适用于输入和输出等长的任务
然而,大多数情况下,
机器翻译的输出和输入都不是等长的。
新架构
“编码器-解码器”架构
前半部分的RNN只有输入;
后半部分的RNN只有输出。
(上一轮的输出会当作下一轮的输入以补充信息)
缺点:编码器和解码器之间只通过一个隐状态来传递信息
在处理较长的文章时,
这种架构的表现不够理想。
新架构
基于注意力的架构
这种架构依然使用了编码器和解码器,
只不过解码器的输入是编码器的状态的加权和,
而不再是一个简单的中间状态。
缺点:RNN的训练通常比较缓慢
尽管注意力模型的表现已经足够优秀,
但所有基于RNN的模型都面临着同样一个问题:
RNN本轮的输入状态取决于上一轮的输出状态,
这使RNN的计算必须串行执行
新架构
只使用注意力机制的Transformer

“编码器-解码器”架构:两个部分通过一个状态a<Tx>来传递信息。把该状态看成输入信息的一种编码的话,前半部分可以叫做“编码器”,后半部分可以叫做“解码器”。

imgimage-20240801102514838

这种架构因而被称为“编码器-解码器”架构。

基于注意力的架构:

每一个输出对每一个输入的权重叫做注意力,注意力的大小取决于输出和输入的相关关系。这种架构优化了编码器和解码器之间的信息交流方式,在处理长文章时更加有效。

  • 注意力:权重(输出 ← 输入)

imgimage-20240801103217833

 


 

框架:编码器 + 解码器

补充 从上面的图可以看到Transformer的组成为:Encoder + Decoder(参考博文2的行文思路)

对于Encoder而言:

对于Decoder而言:

 

 

encoder和decoder的区别:

 

↑ 传统的encoder-decoder做法。


↓ Transformer中的encoder-decoder做法。

img

Transformer是将self-attentionpoint-wisefully-connected layers进行堆叠行程encoderdecoder架构。

左边就是编码器,右边就是解码器。

如果是一个中文翻译英文的任务:

编码器和解码器都是由若干个Transformer Block组成。

一个Transformer Block主要由这三个基础元素构成:
Feed Forward:前馈神经网络 MLP
Multi-Head attention:多头注意力机制(可能包含自注意力、掩码机制)
Add & Norm:残差连接+Layernorm

Input Embedding

Nx

 

编码器

编码器中,一个Transformer Block由两个子块组成:

两个子块组成了编码器的Transformer Block,N个编码器Transformer Block组成最后的编码器。

解码器

解码器中,一个Transformer Block由三个子块组成:

这里的每个子块依旧使用的是残差连接,最后使用layer normalization,三个子块构成了解码器的Transformer Block,N个编码器Transformer Block组成最后的解码器。

 

编码器的结构

编码器就是重复6个前面提到的编码器Transformer Block,所以前面提到的N,它等于6(N=6)。

解码器的结构

解码器和编码器主体上比较相似,也是由6个Transformer Block堆叠而成。

Decoder —— 1个Transformer Block
残差连接+LayerNorm
残差连接+LayerNorm
sub-layer3: Feed Forward 编码器的sub-layer2
sub-layer2: Muti-head Attention 编码器的sub-layer1
sub-layer1: Masked Muti-head Attention

注意力(Attention)

一个注意力函数就是将一个query和一些key-value对映射成一个输出的函数。

Scaled Dot-Product Attetion(缩放点积注意力)

输入由大名鼎鼎的Q、K、V组成。

  • Q:query

  • K:key,dk

  • V:value,dv

K和V,一般是键值对的形式存在。

步骤描述:

1 首先,计算query和所有key的点积;

2 点积除以缩放因子(dk)得到一个结果;

3 这个结果再经过softmax获得一组权重,这个权重对value进行重构就是注意力机制的结果。

其中,经过softmax计算得到的权重,代表的意义是query和key的相似度

虽然key-value都没有发生变化,但是随着query的改变,因为权重的分配不一样,导致输出会有不一样,这就是所谓的注意力机制。这个过程的两种表示如下:

图片表示公式表示
imgAttention(Q,K,V)=softmax(QKTdk)V

Softmax补充说明

相似度补充说明

实际计算

计算思路是上面说的思路,但是实际计算的时候不会一个query、一个query的计算,因为运算比较慢。

普遍的计算方法:把多个query写成一个矩阵,并行化运算。

  • Qn×dk (矩阵的维度)

  • Km×dk (矩阵的维度)

  • QKT(n×dk)×(m×dk)T=(nm) (点积运算之后,结果矩阵的维度)

一个query对所有key的内积值,然后再除以dk,再做softmax。

Attention的计算就是两次矩阵乘法、并行计算。

Scale Dot-Product Attetion补充说明

和其他注意力的区别

2种常见的注意力机制:

多头(mutli-head)

  • 单头注意力就是self-Attention,即原始输入 X 经过self-Attention后生成 Z 向量。

  • 多头注意力,Multi-head,这里的head代表头数,所以这个head等于多少是自己定义的。

重述 这篇论文的注意力机制的运作方式:

1 在原始数据的基础上生成一组Q, K, V向量;

2 再由这组Q, K, V向量生成最后的注意力结果。


而Multi-head的做法,就是生成多组Q, K, V,使用Attention得到多个结果,再将多个结果进行加权平均得到最后的结果。

这个过程的两种表示如下:

图片表示公式表示
imgMultihead(Q,K,V)=Concat(head1,,headh)WOwhereheadi=Attention(QiQ,KiK,ViV)

原始输入X,分别乘上一组可学习权重WQWKWV,生成一组Q, K, V向量。

在过程1中,是一组Q, K, V向量;多头则生成 hQ, K, V向量。

hQ, K, V向量均使用缩放点积注意力生成 hZ向量,使用concat拼接操作,将 hZ向量拼接成一个,再经过一组可学习参数生成最后的输出。

掩码多头注意力(Masked Multi-Head Attetion)

Mask就是掩码的意思。

由于Attention机制的缘故,每次都必须看到句子的全部。但是在生成的时候是一个一个生成的:也就是说在 t 时刻是不可以看到 t 时刻之后的东西的

因此,作者设置了一个掩码机制:就是在解码器的内部,输入数据之前,先经过一层Masked Multi-Head Attention。这层网络会将 t 时刻之后的数据有效性给抹杀掉。

作用t 时刻之后的数据失效。(避免在 t 时刻看到 t 时刻之后的数据)

 

解码器的多头注意力机制(Multi-Head Attention)

在解码器中,不再是使用的自注意力。解码器的 KV是来自编码器输出,而 Q 是来自解码器的Masked Multi-Head Attention的输出

image-20240810174950392

 

三个多头注意力的使用情况

在Transformer模型中,(在不考虑Transformer Block堆叠的情况下)一共有三种使用多头注意力的情况,分别是编码器中的注意力层、解码器的掩码注意力层、解码器的第二个注意力层。

image-20240810180042845

处使用:

处使用:

处使用:

 

Position-wise MLP

前面我们提到一个Transformer Block主要由三部分组成,分别是:

文中的MLP全称是Position-wise Feed-Forward Networks,这里的MLP由两层Linear组成,之间有一层ReLU:

(3)FFN(x)=max(0,xw1+b1)w2+b2

MLP:原文解释 —— applied to each position separately and identically

Point-wise:把一个MLP对每一个词(Position)作用一次,对每个词作用的是同样的MLP

FFN:Linear + ReLU + Linear

单隐藏层的MLP,中间w1扩维到4倍(2048),最后w2投影回到512维度大小,便于残差连接。

PyTorch实现:2个线性层。

最简单情况:没有残差连接、没有LayerNorm、Attention单头、没有投影。

 

Attention与RNN进行比较

 

embeddings and softmax

我们的输入是一个一个的词(=词源=token),需要将词映射成一个向量。

含义 embedding的意思是给任何一个词,学习一个长为 d 的向量表示它(在本文中d=512)。

编码器、解码器、最后softmax之前的3个embedding共享权重。 → 训练更简单。

Note:权重*sqrt(dmodel=512),学embedding的时候,会把每一个向量的L2 Norm学的比较小。

 

Position encoding

Question 为什么Attention不会有时序信息呢?

Answer 因为Transformer Block的注意力机制是对value进行重构,对value进行重构的权重是query和key之间的距离,和序列信息无关。

 

问题引入 把一句话的词相对顺序进行了改变,但是结果不变,这岂不是错误?

因此,position encoding的作用就是加入时序信息(所谓时序信息就是先后顺序之间的关系)

由于我们的模型不包含循环和卷积,为了让模型利用序列的顺序,我们必须注入序列中关于词符相对或者绝对位置的一些信息。为此,我们将“位置编码”添加到编码器和解码器堆栈底部的输入嵌入中

在这项工作中,我们使用不同频率的正弦和余弦函数:

(4)PEpos,2i=sin(pos/100002i/dmodel)PEpos,2i+1=cos(pos/100002i/dmodel)

思路:在RNN中将上一个时刻的输出加入到下一时刻的输入中,以此来传递时序信息。假设有一个词,它在位置 i 处,会将 i 位置信息加入到输入里面,如位置12345。

计算机表示一个32位的整数:32个bit,每个bit上有不同的值来表示。

一个词在嵌入层表示成一个512维的向量,用另一个512维的向量来表示一个数字,位置信息 1 2 3 4 5 6 7 8 ...

表示一个位置数字信息的值,怎么计算?

Demo 假如有一个英文句子,里面有7个单词。经过embedding后就会变成一个(7,512)的向量,由于positional encoding的原因,它还会生成一个(7,512)的向量表示位置信息,而(7,512)数据的来源是用这两个公式计算出来的:

(5)PEpos,2i=sin(pos/100002i/dmodel)PEpos,2i+1=cos(pos/100002i/dmodel)

为什么使用注意力机制

在前面的内容中,论文主要介绍了模型整体架构,并对每个组件进行了解释。

作者在这部分将进行解释,为什么这样做以及设计理念。

image-20240811173501861

如图所示,一共有3列进行比较。

  1. 第一列:计算复杂度,越低越好;

  2. 第二列:顺序的计算,越少越好;

    顺序的计算指的是你下一步的计算必须要等前面多少步计算完成,在算一个layer的时候,等待的越少,那么并行度就会越高。

  3. 第三列:信息从一个数据点到另一个数据点需要走多远,也是越短越好。

 

一共有自注意力、循环、卷积、自注意力(带限制)这四种网络,分别介绍一下这4种网络的数值是如何计算的。

自注意力网络

因为sequential operations就是那么几个矩阵乘法,矩阵里面可以认为并行度是比较高的,所以这个地方是O(1)。

最大长度是从一个点跳到另一个点要走多少步。

 

循环神经网络

循环层我们知道,如果你的序列是乘了 n 的话,它就一个一个做运算,每个里面它的主要计算就是一个 d×d的一个矩阵,就是一个dense layer,然后再乘以一个长为 n 的一个输入。

在计算复杂度上,与自注意力相比取决于 dn 谁比较大。

 

卷积神经网络

我们没有特别解释卷积在序列上怎么做。具体做法是它用一个1d的卷积,所以它的kernal就是 k ,不是 kn 是你的长度,d 呢就是输入通道数和输出通道数。k 一般就是3/5之类的,可以认为是常数。

卷积的好处是经过一次卷积就完成了,里面的并行度很高,所以卷积做起来,通常比RNN要快一点。

卷积每一个是由一个长为 k 的窗口来看,所以一个信息在 k 距离内是能够一次传递,如果你超过了 k,要传递信息的话,要通过多层一层一层上去,但它是一个 log 的操作,所以这个东西也不亏。

被限制的自注意力网络

当我做注意力的时候,我的query只跟我最近的 r 个邻居去做运算,这样就不用去算 n2 这个东西了。

一般来说,在实际中用Attention主要是关心特别长的序列,能够把信息揉的比较好一点,所以在实际过程中,self-Attention(restricted)用的不是那么多,搭建都是用最原始的版本。

(ps:如果在语音识别方向,会用到restricted,可以让语音识别变成实时的)

实际中,当你的序列长度和你模型的宽度差不多的时候,而且大家深度都一样的话,基本上三个模型的算法复杂度都是差不多的。

当然,你的Attention和卷积相对来说计算会好一点,另外一个是说Attention在信息的糅合性上会好一点,所以你可以认为这个地方还是能影响一些东西。

所以看上去是说用了self-Attention之后对长数据处理得更好,而且算的不快也不会慢。

但实际上并不是这个样子,Attention对模型得假设做了更少,导致需要更多的数据和更大的模型才能训练出来,达到跟RNN和CNN同样的效果

所以导致现在基于Transformer的模型呢都是特别大、特别贵。

 

训练&结果

本文主要使用了2个翻译任务,一个是英语 → 德语;一个是英语 → 法语。接下来分两个部分来介绍一下。

训练数据和批次

Transformer英语翻译德语

首先谈到了训练数据集batch是如何处理的,前面谈到了LayerNorm和BatchNorm是分别对Feature和Batch做Norm。

英语翻译德语,用的是标准的WMT2014任务,有4500万个句子对,使用了bpe(byte-pair encoding)来做词嵌入

Transformer英语翻译德语任务使用的是37000个token的一个字典,而且它是在英语和德语之间是共享的:

(ps:词向量,Word embedding,又叫Word嵌入式,自然语言处理中的一组语言建模和特征学习技术的统称,其中来自词汇表的单词或短语被映射到实数的向量。)

Transformer英语翻译法语

这个任务使用了一个更大的数据集,在接下来的硬件和schedule部分,训练使用8个p100的GPU

(三年前google的大量工作还是使用GPU的,但是之后google就让内部员工尽量使用tpu,Transformer里面基本都是比较大的矩阵做乘法,tpu适合处理大的矩阵乘法)

它说我们的base模型使用一个小一点的参数,每一个batch的训练时间是0.4s,一共训练了10w步,在8个GPU上训练了12个小时。就是基本上一台机器训练12个h也是不错的性能。

对于大的模型,一个batch训练需要1秒钟,他一共训练了30w步,一台机器3.5天。这其实也是可承受的范围,但之后所出现的工作很难承受。

在训练器上面使用的是Adam,β2应该不是最常用的,应该是0.99还是0.999,所以它选了一个稍微小一点的值。

学习率是用这个公式算出来的:

(6)learning_rate=dmodel0.5min(stepNum0.5,stepNumwarmupSteps1.5)

有意思的是学习率是根据你模型的宽度的-0.5次方,就是说模型越宽,就是你学习的向量越长的时候。你的学习率要低一点,另外一点是它有个warmup,就是从一个小的值慢慢地爬到一个高的值,最后再跟你的步数按照0.5次方衰减,最后它说我的warmup_step是4000。

有意思的是几乎可以看到这个地方没有东西是可以调的,取决于:

 

硬件和步长

作者在一台具有8个NVIDIA P100 GPU的机器上训练Transformer模型。

使用本文描述的超参数的基础模型,每个训练步骤耗时约0.4秒。

基础模型共训练了10万步,约12小时。

对于我们的大模型(如表的底部所示),步长为1.0秒,大模型训练了30万步(3.5天)。

image-20240812181305333

正则化

训练期间采用三种正则化:

残差丢弃:我们将丢弃应用到每个子层的输出,在将它与子层的输入相加和规范化之前。此外,在编码器和解码器堆栈中,我们将丢弃应用到嵌入和位置编码的和。对于基本模型,我们使用Pdrop=0.1丢弃率。

Label Smoothing:在训练过程中,我们使用的label smoothing的值为ϵls=0.1。这让模型不易理解,因为模型学得更加不确定,但提高了准确性和BLEU得分。

 

结果:机器翻译任务

在WMT 2014英语-德语翻译任务中,大型Transformer模型(表2中的Transformer(big))比以前报道的最佳模型(包括整合模型)高出2.0个BLEU以上,确立了一个全新的最高BLEU分数为28.4。该模型的配置列在表3的底部。训练在8个P100 GPU上花费3.5天。即使我们的基础模型也超过了以前发布的所有模型和整合模型,且训练成本只是这些模型的一小部分。

在WMT 2014英语-法语翻译任务中,我们的大模型的BLEU得分为41.0,超过了之前发布的所有单一模型,训练成本低于先前最先进模型的1/4。英语-法语的Transformer(big)模型使用丢弃率为Pdrop=0.1,而不是0.3。

对于基础模型,我们使用的单个模型来自最后5个检查点的平均值,这些检查点每10分钟写一次。对于大型模型,我们对最后20个检查点进行了平均。我们使用beam search,beam大小为4,长度惩罚α=0.6。这些超参数是在开发集上进行实验后选定的。在推断时,我们设置最大输出长度为输入长度+50,但在可能时尽早终止。

image-20240812181122897

表2总结了我们的结果,并将我们的翻译质量和训练成本与文献中的其他模型体系结构进行了比较。我们通过将训练时间、所使用的GPU的数量以及每个GPU的持续单精度浮点能力的估计相乘来估计用于训练模型的浮点运算的数量。

 

 

 

正文

摘要

 

About注意力

名称:注意力

计算:做1次“注意力”计算

 

Scaled Dot-Product Attention(放缩点乘注意力)

(9)Attention(Q,K,V)=softmax(QKTdk)V
符号含义实例(在上一个问题中对应的具体对象)
Kkey向量的数组K=[[1,2,0],[1,2,0],[0,0,2],[1,4,0]]
Vvalue向量的数组而在我们刚刚那个例子里,value都是实数。
实数其实也就是可以看成长度为1的向量。
V=[[18],[20],[22],[19]]

在刚刚的例子中,我们只做了1次查询,所以公式可以改写为:

(10)MyAttention(q,K,V)=softmax(qKT)V

其中,query,也就是q则为[1, 0, 0]

实际上,我们也可以一次做多组query,把所有的q打包成矩阵Q,就得到了上述的公式:

(11)Attention(Q,K,V)=softmax(QKTdk)V
符号含义实例(在上一个问题中对应的具体对象)
Kkey向量的数组K=[[1,2,0],[1,2,0],[0,0,2],[1,4,0]]
每个组成被称为key向量,所有加起来叫做key向量的数组。
Vvalue向量的数组而在我们刚刚那个例子里,value都是实数。
实数其实也就是可以看成长度为1的向量。
V=[[18],[20],[22],[19]]dv=1
dkquery和key向量的长度
由于query和key要做点乘,这两种向量的长度必须一致。
value向量的长度倒是可以不一致,
论文里把value向量的长度叫做dv
在我们这个例子里,dk=3,dv=1
key向量示例:[1,2,0];长度为3;
query向量:[1,0,0];长度为3。

 

为什么要用一个和dk成比例的项来放缩QKT呢?

这是因为,softmax在绝对值较大的区域梯度较小,梯度下降的速度比较慢。因此,我们要让被softmax的点乘数值尽可能小。而一般在dk较大时,也就是向量较长时,点乘的数值会比较大。除以一个和dk相关的量能够防止点乘的值过大。

简单来说:防止(点乘的值过大 → 导致区域梯度较小 → 梯度下降的速度变慢)

 

关于注意力的解读

收获:点乘可以计算出2个向量之间的相似性

 

注意力

回顾:注意力机制其实就是“全局信息查询”。

补充 具体来说,自注意力机制允许模型同时计算输入序列中所有位置之间的关系权重,进而加权得到每个位置的特征表示。在Transformer模型中,自注意力机制被运用在了Encoder和Decoder两个部分中,分别用于编码输入序列和生成输出序列。


多头自注意力机制(multi-head self-attention)是Transformer模型的核心部分,其作用是从输入序列中学习并计算每个位置与其他位置之间的相关度。具体来说,多头自注意力机制将输入序列中的每个位置看作一个向量,然后对这些向量进行相似度计算,得到每个位置与其他位置之间的相关度

多头自注意力机制将输入序列分别映射成多个维度相同的向量,然后分别应用自注意力机制,得到多个输出向量,最后将这些输出向量拼接起来,得到最终的向量表示。这种分头处理的方法可以使模型更好地捕捉不同方面的特征,从而提高模型的表现。

自注意力模块

 

引子每个单词的query,key,value是怎么得来的? → Transformer里的另一种机制——多头注意力

多头注意力机制

补充 多头注意力机制(multi-head attention)是Decoder中的另一个子层,其作用是计算当前时刻的输入与输入序列之间的关系,并根据这些关系计算出当前时刻的上下文向量表示。

多头注意力机制将输入序列的向量表示与当前时刻的输入向量表示进行相似度计算,得到每个位置与当前时刻输入的相关度。然后,根据这些相关度计算当前时刻的上下文向量表示,用于生成输出序列。与多头自注意力机制类似,多头注意力机制也采用了分头处理的方法,从而更好地捕捉不同方面的特征。

————————————————

首先:在自注意力中,每一个单词的query, key, value应该只和该单词本身有关。

        因此,这三个向量都应该由单词的词嵌入得到。

另外:每个单词的query, key, value不应该是人工指定的,而应该是可学习的

        因此,我们可以用可学习的参数来描述词嵌入query, key, value的变换过程

 

可学习的参数
单词的词嵌入
每一个单词的query,key,value

综上所述:自注意力的输入Q,K,V应该用下面这个公式计算:

(13){Q=EWQK=EWKV=EWV

其中:

  • E词嵌入矩阵,也就是每个单词的词嵌入的数组;

  • WQ,WK,WV是可学习的参数矩阵。

在Transformer中,大部分中间向量的长度都用dmodel表示,词嵌入的长度也是dmodel

        因此,设输入的句子长度为n

                E 的形状是n×dmodel;(E词嵌入矩阵)

                WQ,WK的形状是dmodel×dk

                WV的形状是dmodel×dv

就像卷积层能够用多个卷积核生成多个通道的特征一样,我们也用多组WQ,WK,WV生成多组自注意力结果。这样,每个单词的自注意力表示会更丰富一点。这种机制就叫做多头注意力

把多头注意力用在自注意力上的公式为:

(14)headi=Attention(EWiQ,EWiK,EWiV)MultiHeadSelfAttention(E)=Concat(head1,...headh)WO

Transformer似乎默认所有向量都是行向量,参数矩阵都写成了右乘而不是常见的左乘。

ps: 这句话怎样理解呢?左乘很常见吗?

  • WQ,WK,WV是可学习的参数矩阵。

  • 参数矩阵都写成了右乘,而不是常见的左乘。

 

在论文中,Transfomer的默认参数配置如下:

实际上,多头注意力机制不仅仅可以用在计算自注意力上。推广一下,如果把多头注意力的输入 E 拆成三个矩阵 Q,K,V,则多头注意力的公式为:

(15)headi=Attention(QWiQ,KWiK,VWiV)MultiHeadAttention(Q,K,V)=Concat(head1,...headh)WO

 

Transformer模型架构

image-20240804153140790image-20240804153420797

 

残差连接

Transformer使用了和ResNet类似的残差连接,即:

和ResNet不同,Transformer使用的归一化方法是LayerNorm。

 

残差连接有一个要求:

 

在Transformer中,包括所有词嵌入在内的向量长度都是dmodel=512

 

前馈网络

补充 前馈网络(feedforward network)是Encoder层的另一个子层,其作用是对多头自注意力机制的输出向量进行非线性变换。前馈网络由两个线性变换和一个激活函数组成,其中线性变换将输入向量映射到一个高维空间,激活函数将这个高维向量进行非线性变换,最后再将其映射回原始维度。

各组件作用:

  • 线性变换:将输入向量映射到一个高维空间;

  • 激活函数:将这个高维向量进行非线性变化,最后再将其映射回原始维度。

架构图中的前馈网络(Feed Forward)其实就是一个全连接网络

 

整体架构与掩码多头注意力

早期生成序列的模型 早期基于RNN的序列转换模型在生成序列时一般会输入前 i 个单词,输出第 i+1 个单词。

img

用Transformer生成序列 Transformer使用了encoder-decoder的架构:

对比:

image-20240804155059273

Transformer默认会并行地输出结果。而在推理时,序列必须得串行生成。

直接调用Transformer的并行输出逻辑会产生非常多的冗余运算量。推理的代码实现可以进行优化。

image-20240804163623176

具体来说,输入序列x会经过N=6个结构相同的层。每层由多个子层组成。

简 将 访 问 非 洲。
  1. 第一个子层是多头注意力层,准确来说,是多头自注意力。

    这一层可以为每一个输入单词提取出更有意义的表示

  2. 之后数据会经过前馈网络子层。最终,输出编码结果 z

  3. 得到了 z 后,要用解码器输出结果了。

    解码器的输入当前已经生成的序列,该序列会经过一个掩码(masked)多头自注意力层。我们先不管这个掩码是什么意思,暂且把它当成普通的多头自注意力层它的作用和编码器中的一样,用于提取出更有意义的表示

  4. 接下来,数据还会经过一个多头注意力层。这个层比较特别,它的K,V来自zQ来自上一层的输出。

    为什么会有这样的设计呢?

    这种设计来自于早期的注意力模型。如下图所示,在早期的注意力模型中,每一个输出单词都会与每一个输入单词求一个注意力,以找到每一个输出单词最相关的某几个输入单词。用注意力公式来表达的话,Q就是输出单词,K,V就是输入单词。

    img

  5. 经过第二个多头注意力层后,和编码器一样,数据会经过一个前馈网络。最终,网络并行输出各个时刻的下一个单词。

image-20240804164247778

image-20240804163522545

Masked

这种并行计算有一个要注意的地方。在输出第t+1个单词时,模型不应该提前知道t+1时刻之后的信息。因此,应该只保留t时刻之前的信息,遮住后面的输入。这可以通过添加掩码实现。添加掩码的一个不严谨的示例如下表所示:

输入输出
(y1, y2, y3, y4)y2
(y1, y2, y3, y4)y3
(y1, y2, y3, y4)y4

这就是为什么解码器的多头自注意力层前面有一个masked。在论文中,mask是通过令注意力公式的softmax的输入为来实现的(softmax的输入为,注意力权重就几乎为0,被遮住的输出也几乎全部为0)。

 

 

嵌入层

看完了Transformer的主干结构,再来看看输入输出做了哪些前后处理。

image-20240804153140790img

和其他大多数序列转换任务一样,Transformer主干结构的输入输出都是词嵌入序列

在Transformer中,解码器的嵌入层和输出线性层是共享权重的

论文中写道:“输入输出的嵌入层和softmax前的线性层共享权重”。这个描述不够清楚。如果输入和输出的不是同一种语言,比如输入中文输出英文,那么共享一个词嵌入是没有意义的。

嵌入矩阵的权重乘了一个dmodel

由于模型要预测一个单词,输出的线性层后面还有一个常规的softmax操作。

 

对上面一段话我的理解是:

image-20240805110648098

 

位置编码

现在,Transformer的结构图还剩下一个模块没有读——位置编码。

对比 无论是RNN还是CNN,都能自然地利用到序列的先后顺序这一信息。

然而,Transformer的主干网络并不能利用到序列顺序信息。因此,Transformer使用了一种叫做“位置编码”的机制,对编码器和解码器的嵌入输入做了一些修改,以向模型提供序列顺序信息

位置编码的意义 所以:Transformer的位置编码,就是为了向模型提供“序列顺序信息”的。

image-20240805154939037

第1句:嵌入层的输出是一个向量数组,即词嵌入向量的序列

个人理解:

  • 假设是这样的::[[1,2,0],[1,2,0],[0,0,2],[1,4,0]],如果它是词嵌入向量的序列

    • 那么,❶一个词嵌入向量是:[1,2,0]

      • (?) 那么一个词嵌入就是:1。

第2句设数组的位置叫 pos ,向量的某一维叫 i

个人理解:

  • 什么叫做“数组的位置 pos”?

    • 疑惑

  • 什么叫做向量的“某一维 i ”?

    • 在❶中,已经知道,一个词嵌入向量是:[1,2,0]

      • 是不是说:像120这就是向量的第1维度第2维度第3维度分别对应的值。

第3句我们为每一个向量里的每一个数添加一个实数编码,这种编码方式要满足以下性质:

  1. 【性质1】对于同一个pos不同的 i ,即对于一个词嵌入向量的不同元素,它们的编码要各不相同。

    • 即,120这3个维度(i不同)对应的编码要各不相同。

  2. 【性质2】对于向量的同一个维度处,不同pos的编码不同。且pos间要满足相对关系,即

    (17)f(pos+1)f(pos)=f(pos)f(pos1)
    • 不同pos的含义是什么呢?

      疑惑数组的位置被称为pos,那么不同pos的前提是有多个数组啊,同一个数组(词嵌入向量的序列)哪有什么不同的位置的说法呢?!


要满足这2种性质,我们可以轻松地(我感觉不轻松,甚至感觉到了压力 :P)设计一种编码:

(18)Encoding(pos,i)=pos1000i

但是,这种编码不利于网络的学习。所以,我们在设计网络的时候,要考虑它的可学习性,因为这样的话,才能让代码跑起来之后,自己学参数,不用人工调参

目标 我们更希望所有编码都差不多大小,且都位于0~1之间。

行动 为此,Transformer使用了三角函数作为编码函数

这种位置编码(Positional Encoding, PE)的公式如下:

(19)PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)

本文作者也尝试了用可学习的函数作为位置编码函数。实验表明,二者的表现相当。作者还是使用了三角函数作为最终的编码函数,这是因为三角函数能够外推到任意长度的输入序列,而可学习的位置编码只能适应训练时的序列长度。

 

自注意力层的优点(why 自注意力层)

与循环层、卷积层做了对比之后,结论如下。

img

 

前两个指标很容易懂,第三个指标最大路径长度需要解释一下。

最大路径长度:数据从某个位置传递到另一个位置的最大长度。

  • 比如对边长为n的图像做普通卷积操作,卷积核大小3x3,要做n/3次卷积才能把信息从左上角的像素传播到右下角的像素。

    • 设卷积核边长为k,则最大路径长度O(n/k)

      • 如果是空洞卷积的话,像素第一次卷积的感受野是3x3,第二次是5x5,第三次是9x9,以此类推,感受野会指数级增长。这种卷积的最大路径长度是O(logk(n))

我们可以从这三个指标分别探讨自注意力的好处。

1 首先看序列操作的复杂度

2 再看每一层的复杂度

3 最后是最大路径长度

为了降低每层的计算复杂度,可以改进自注意力层的查询方式,让每个元素查询最近的r个元素。本文仅提出了这一想法,并没有做相关实验。

 

实验结果

本工作测试了“英语-德语”和“英语-法语”两项翻译任务。使用论文的默认模型配置,在8张P100上只需12小时就能把模型训练完。本工作使用了Adam优化器,并对学习率调度有一定的优化。

模型有两种正则化方式:

1)每个子层后面有Dropout,丢弃概率0.1;

2)标签平滑(Label Smoothing)。

Transformer在翻译任务上胜过了所有其他模型,且训练时间大幅缩短。


论文同样展示了不同配置下Transformer的消融实验结果。

img

实验A表明:在计算量不变的前提下,需要谨慎地调节h和hk,hv的比例,太大太小都不好。这些实验也说明,多头注意力比单头是要好的。

实验B表明:dk增加可以提升模型性能。作者认为,这说明计算key,value相关性是比较困难的,如果用更精巧的计算方式来代替点乘,可能可以提升性能。

实验C、D表明,大模型是更优的,且dropout是必要的。

如正文缩写,实验E探究了可学习的位置编码。可学习的位置编码的效果和三角函数几乎一致。

 

总结

动机为了改进RNN不可并行的问题,这篇工作提出了Transformer这一仅由注意力机制构成的模型。

效果:Transformer的效果非常出色,不仅训练速度快了,还在两项翻译任务上胜过其他模型。

作者也很期待Transformer在其他任务上的应用。对于序列长度比较大的任务如图像、音频、视频,可能要使用文中提到的只关注局部的注意力机制。由于序列输出时仍然避免不了串行,作者也在探究如何减少序列输出的串行度。

现在来看,Transformer是近年来最有影响力的深度学习模型之一。它先是在NLP中发扬光大,再逐渐扩散到了CV等领域。文中的一些预测也成为了现实,现在很多论文都在讨论如何在图像中使用注意力,以及如何使用带限制的注意力以降低长序列导致的计算性能问题。

我(博文作者)认为,对于深度学习的初学者,不管是研究什么领域,都应该仔细学习Transformer。

在学习Transformer之前,最好先了解一下RNN和经典的encoder-decoder架构,再学习注意力模型。

学习路线
CNN
Transformer
RNN
encoder-decoder架构

有了这些基础,读Transformer论文就会顺利很多。读论文时,最重要的是看懂注意力公式的原理,再看懂自注意力和多头注意力,最后看一看位置编码。其他一些和机器翻译任务相关的设计可以不用那么关注。

关于注意力
注意力公式的原理
自注意力
多头注意力
位置编码

 

特别强调:

  1. 注意力机制不仅仅是Transformer里有的,其他地方也有。只是Transformer里只用了注意力机制。

 

 

 

最后全文搂一遍,看看能不能有什么可以汲取的内容吧!
LaTeX
...

 

 

 

参考博文

  1. Attention Is All You Need (Transformer) 论文精读

  2. 补充 经典论文学习:Attention Is All You Need(Transformer) 这篇文章有点对“注意力、自注意力、掩码注意力区分不明的感觉”

  3. 补充 Transformer:《Attention is all you need》(论文精读/原理解析/模型架构解读/源码解析/相关知识点解析/相关资源提供)

 

 

博文免责声明

  1. 本条博文信息主要整合自网络,部分内容为自己的理解写出来的,如有断章截句导致不正确或因个人水平有限未能详尽正确描述的地方,敬请各位读者指正;

  2. 引用出处可能没有完全追溯到原始来源,如因此冒犯到原创作者,请联系本人更正/删除;

  3. 博文的发布主要用于自我学习,其次希望帮助到有共同疑惑的朋友。

欢迎随时联系讨论,一起成长进步。