Transformer是近年来深度学习领域最重要的架构之一,它彻底改变了自然语言处理,也延伸到了计算机视觉、语音识别等领域。但很多人对Transformer的理解,只停留在"注意力机制"这个层面,对它的底层原理和架构细节,理解得不够深入。今天,我们来深入剖析Transformer的架构原理,从注意力机制到编码器解码器,从位置编码到前馈网络,一步步搞懂它的底层机制。

先说说Transformer的背景。Transformer,是2017年由Google Brain团队在论文《Attention Is All You Need》中提出的。在Transformer之前,自然语言处理的主流架构,是RNN(循环神经网络)和LSTM(长短期记忆网络),这些架构是按顺序处理序列的,一个词一个词地处理,这样有两个问题:一是无法并行计算,处理速度慢;二是长距离依赖问题,序列太长的时候,前面的信息容易丢失。

Transformer的出现,彻底改变了这一点。它完全基于注意力机制,不需要循环结构,可以并行计算整个序列,处理速度快,而且能很好地捕捉长距离依赖。Transformer提出之后,很快就成为了自然语言处理的主流架构,后来的BERT、GPT、T5等著名模型,都是基于Transformer的。

而且,Transformer的应用,已经远远超出了自然语言处理,延伸到了计算机视觉(ViT)、语音识别(Whisper)、多模态(CLIP)、蛋白质结构预测(AlphaFold)等领域,成为了一个通用的深度学习架构。

所以,理解Transformer的原理,对于学习深度学习和AI,是非常重要的。今天,我们就来深入剖析它的架构原理。

一、注意力机制:Transformer的核心

要理解Transformer,首先要理解注意力机制(Attention Mechanism),因为Transformer的核心,就是注意力机制。

1. 什么是注意力机制?

注意力机制,灵感来源于人类的视觉注意力。人类在看东西的时候,不会把注意力平均分配到整个画面,而是会把注意力集中在重要的部分,忽略不重要的部分。比如,你看一张照片,会首先注意到照片中的人,而不是背景。

注意力机制,就是让模型在处理信息的时候,也能像人类一样,把注意力集中在重要的部分,给重要的部分更高的权重,给不重要的部分更低的权重。

在自然语言处理中,注意力机制,就是让模型在处理一个词的时候,能够关注到句子中其他相关的词,给相关的词更高的权重,给不相关的词更低的权重。这样,模型就能更好地理解词与词之间的关系,更好地理解整个句子的意思。

比如,句子"我把苹果放在桌子上,因为它很新鲜",这里的"它"指的是"苹果",而不是"桌子"。注意力机制,就能让模型在处理"它"的时候,给"苹果"更高的权重,从而正确理解"它"指的是什么。

2. 自注意力机制(Self-Attention)

Transformer中用的,是自注意力机制(Self-Attention),也叫内部注意力机制。自注意力,就是序列中的每个词,都和序列中的所有词(包括自己)计算注意力,从而捕捉词与词之间的关系。

自注意力的计算过程,可以用三个矩阵来表示:Query(查询,Q)、Key(键,K)、Value(值,V)。这三个矩阵,都是由输入序列通过线性变换得到的。

计算过程是这样的:

  1. 用Query和Key计算注意力分数:Attention(Q, K, V) = softmax(QK^T / sqrt(d_k))V
  2. 具体来说,对于每个词的Query,和所有词的Key做点积,得到注意力分数。
  3. 把注意力分数除以sqrt(dk)(dk是Key的维度),进行缩放,防止点积太大导致softmax梯度消失。
  4. 用softmax函数,把注意力分数转换成注意力权重,权重之和为1。
  5. 用注意力权重,对所有词的Value进行加权求和,得到这个词的自注意力输出。

这个过程,可能有点抽象,举个简单的例子。假设句子是"我 爱 中国",三个词。对于"爱"这个词:

  • 它的Query,和"我"的Key、"爱"的Key、"中国"的Key,分别做点积,得到三个分数。
  • 假设分数是:和"我"的分数是2,和"爱"的分数是1,和"中国"的分数是3。
  • 除以sqrt(d_k)之后,用softmax转换成权重,假设权重是:"我"0.2,"爱"0.1,"中国"0.7。
  • 然后,用这三个权重,对三个词的Value加权求和,得到"爱"这个词的自注意力输出。

这样,"爱"这个词的输出,就融合了"我"和"中国"的信息,而且给"中国"更高的权重,因为"爱"和"中国"的关系更密切。

这就是自注意力的核心思想:每个词的表示,都融合了整个序列的信息,而且根据相关性,给不同的词不同的权重。

3. 多头注意力(Multi-Head Attention)

Transformer中,用的不是单头的自注意力,而是多头注意力(Multi-Head Attention)。多头注意力,就是把Q、K、V分成多个头,每个头独立计算自注意力,然后把多个头的结果拼接起来,再做一次线性变换。

为什么要用多头注意力呢?因为不同的头,可以关注不同的关系。比如,一个头关注语法关系,一个头关注语义关系,一个头关注指代关系,等等。多个头并行计算,可以捕捉更丰富的信息,让模型的表达能力更强。

多头注意力的计算过程:

  1. 把Q、K、V分别线性变换,然后分成h个头(h一般是8或者16)。
  2. 每个头,独立计算自注意力,得到每个头的输出。
  3. 把h个头的输出拼接起来,得到一个完整的输出。
  4. 对拼接后的输出,再做一次线性变换,得到最终的多头注意力输出。

多头注意力,是Transformer的一个重要设计,它让模型能够同时关注不同类型的关系,大大提升了模型的表达能力。

二、位置编码:让模型知道词的顺序

自注意力机制,有一个问题:它是对序列中的所有词,并行计算的,没有考虑词的顺序。也就是说,把句子中的词打乱顺序,自注意力的计算结果是一样的。但在自然语言中,词的顺序是非常重要的,"我打你"和"你打我",词是一样的,但意思完全相反。

所以,Transformer需要一种方式,让模型知道词的顺序,这就是位置编码(Positional Encoding)。

1. 什么是位置编码?

位置编码,就是给每个位置的词,加上一个位置信息,让模型知道这个词在序列中的位置。这样,模型就能区分不同位置的词,理解词的顺序。

Transformer用的位置编码,是正弦余弦位置编码,公式是这样的:

  • PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
  • PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

其中,pos是词的位置,i是维度的索引,d_model是模型的维度。

这个位置编码,有几个特点:

  1. 每个位置,都有一个唯一的位置编码向量。
  2. 位置编码的每个维度,都是一个正弦或者余弦函数,不同的维度,频率不同。
  3. 对于任意一个固定的偏移k,PE(pos+k)可以表示成PE(pos)的线性函数,这样模型就能很容易地学习到相对位置关系。

2. 位置编码怎么用?

位置编码的用法很简单:把输入词的词嵌入(Word Embedding),和对应位置的位置编码,相加起来,作为Transformer的输入。

也就是说,输入 = 词嵌入 + 位置编码。

这样,每个词的表示,就既包含了词本身的语义信息,又包含了位置信息,模型就能同时理解词的语义和顺序。

为什么是相加,而不是拼接呢?因为相加可以保持维度不变,不需要增加模型的参数,而且实践证明,相加的效果很好。

3. 其他位置编码方式

正弦余弦位置编码,是原始Transformer用的方式。后来,人们又提出了很多其他的位置编码方式,比如:

  • 可学习的位置编码:把位置编码当成可学习的参数,让模型自己学习。BERT用的就是这种方式。
  • 相对位置编码:不编码绝对位置,而是编码词与词之间的相对位置。
  • 旋转位置编码(RoPE):把位置信息编码到Query和Key的旋转中,在长序列中效果很好。LLaMA等大模型用的就是这种方式。

这些位置编码方式,各有优缺点,但核心思想都是一样的:让模型知道词的顺序,理解词与词之间的位置关系。

三、编码器:理解输入序列

Transformer的整体架构,是编码器-解码器(Encoder-Decoder)架构。编码器负责理解输入序列,解码器负责生成输出序列。我们先来说说编码器。

1. 编码器的结构

Transformer的编码器,由N层相同的编码器层堆叠而成(原始论文中N=6)。每个编码器层,包含两个子层:

  1. 多头自注意力层(Multi-Head Self-Attention)
  2. 前馈神经网络层(Feed-Forward Network)

每个子层,都有一个残差连接(Residual Connection),然后是层归一化(Layer Normalization)。

也就是说,每个子层的输出是:LayerNorm(x + Sublayer(x))

残差连接,是为了解决深层网络的梯度消失问题,让梯度可以直接传播,模型可以训练得更深。层归一化,是为了稳定训练,加速收敛。

2. 多头自注意力层

编码器中的多头自注意力层,就是我们前面讲的多头自注意力。它让序列中的每个词,都能关注到序列中的所有词,捕捉词与词之间的关系,从而更好地理解整个输入序列。

在编码器中,自注意力是双向的,也就是说,每个词都能关注到它前面和后面的所有词。这对于理解输入序列是很重要的,因为理解一个词,往往需要同时看它的上下文。

3. 前馈神经网络层

前馈神经网络层(Feed-Forward Network,FFN),是一个两层的全连接网络,中间有一个ReLU激活函数。公式是:FFN(x) = max(0, xW1 + b1)W2 + b2

前馈网络的作用,是对每个位置的表示,进行非线性变换,增加模型的表达能力。注意,前馈网络是对每个位置独立应用的,不同位置之间,参数是共享的。

原始Transformer中,前馈网络的中间层维度,是模型维度的4倍。比如,模型维度是512,中间层维度就是2048。

4. 编码器的整体流程

总结一下,编码器的整体流程是:

  1. 输入序列,转换成词嵌入,加上位置编码。
  2. 输入到第一层编码器层。
  3. 在编码器层中,先经过多头自注意力层,加上残差连接,层归一化。
  4. 然后经过前馈神经网络层,加上残差连接,层归一化。
  5. 第一层的输出,作为第二层的输入,重复上述过程。
  6. 经过N层编码器层之后,得到编码器的输出,也就是输入序列的表示。

编码器的输出,是一个和输入序列长度相同的序列,每个位置,都是一个包含了整个输入序列信息的向量。这个输出,会传给解码器,帮助解码器生成输出序列。

四、解码器:生成输出序列

说完了编码器,再来说说解码器。解码器负责生成输出序列,比如在机器翻译中,输入是英文,编码器理解英文,解码器生成中文。

1. 解码器的结构

解码器,也是由N层相同的解码器层堆叠而成(N=6)。每个解码器层,包含三个子层:

  1. 掩码多头自注意力层(Masked Multi-Head Self-Attention)
  2. 编码器-解码器注意力层(Encoder-Decoder Attention)
  3. 前馈神经网络层(Feed-Forward Network)

和编码器一样,每个子层,也都有残差连接和层归一化。

2. 掩码多头自注意力层

解码器中的自注意力,和编码器中的自注意力,有一个重要的区别:解码器中的自注意力,是掩码的(Masked),也就是说,每个词,只能关注到它前面的词,不能关注到它后面的词。

为什么要这样呢?因为解码器是用来生成输出序列的,生成的时候,是一个词一个词地生成的,从左到右。在生成第t个词的时候,只能看到前面已经生成的t-1个词,不能看到后面还没生成的词。如果能看到后面的词,就相当于"作弊"了,模型就不需要学习了,直接抄答案就行。

所以,解码器中的自注意力,要加一个掩码,把后面的词的注意力分数,设成负无穷,这样softmax之后,权重就是0,相当于看不到后面的词。

这就是掩码多头自注意力,它保证了解码器在生成的时候,只能看到已经生成的词,不能看到未来的词。

3. 编码器-解码器注意力层

解码器中的第二个子层,是编码器-解码器注意力层(Encoder-Decoder Attention),也叫交叉注意力(Cross-Attention)。

这个层,和自注意力不同。自注意力的Q、K、V,都来自同一个序列;而编码器-解码器注意力的Q,来自解码器的前一个子层的输出,K和V,来自编码器的输出。

也就是说,解码器在生成每个词的时候,用自己的Query,去关注编码器输出的所有Key和Value,从而从输入序列中,获取需要的信息。

比如,在机器翻译中,解码器在生成中文的某个词的时候,通过编码器-解码器注意力,关注到英文输入中对应的词,从而生成正确的翻译。

编码器-解码器注意力,是连接编码器和解码器的桥梁,它让解码器能够利用编码器对输入序列的理解,生成正确的输出序列。

4. 前馈神经网络层

解码器中的前馈神经网络层,和编码器中的一样,也是一个两层的全连接网络,对每个位置的表示进行非线性变换,增加模型的表达能力。

5. 解码器的输出层

经过N层解码器层之后,解码器的输出,还要经过一个线性层,把维度转换成词表大小,然后用softmax函数,转换成每个词的概率分布。

这样,对于每个位置,模型都会输出一个词表大小的概率分布,表示在这个位置,生成每个词的概率。生成的时候,选择概率最大的词,或者用采样的方式,选择一个词,作为这个位置的输出。

6. 解码器的整体流程

总结一下,解码器的整体流程是:

  1. 已经生成的输出序列,转换成词嵌入,加上位置编码。
  2. 输入到第一层解码器层。
  3. 在解码器层中,先经过掩码多头自注意力层,加上残差连接,层归一化。
  4. 然后经过编码器-解码器注意力层,加上残差连接,层归一化。
  5. 然后经过前馈神经网络层,加上残差连接,层归一化。
  6. 第一层的输出,作为第二层的输入,重复上述过程。
  7. 经过N层解码器层之后,经过线性层和softmax,得到输出词的概率分布。

解码器在生成的时候,是自回归的(Autoregressive),也就是说,生成第一个词,然后把第一个词作为输入,生成第二个词,再把前两个词作为输入,生成第三个词,以此类推,直到生成结束符。

五、Transformer的训练和推理

理解了Transformer的架构,再简单说说它的训练和推理。

1. 训练

Transformer的训练,一般用的是教师强制(Teacher Forcing)的方式。也就是说,在训练的时候,解码器的输入,是真实的输出序列( shifted right,也就是右移一位,前面加一个起始符),而不是模型自己生成的序列。这样,训练的时候,每个位置都能看到真实的前面的词,训练更稳定,收敛更快。

训练的损失函数,一般是交叉熵损失,计算模型预测的词的概率分布,和真实词之间的差距。

因为Transformer可以并行计算,所以训练的时候,整个输出序列可以并行计算,不需要像RNN那样一个词一个词地算,训练速度很快。

2. 推理

推理的时候,就不能用教师强制了,因为没有真实的输出序列。推理的时候,是自回归的,一个词一个词地生成:

  1. 输入起始符,解码器生成第一个词。
  2. 把起始符和第一个词,作为解码器的输入,生成第二个词。
  3. 把前面生成的所有词,作为解码器的输入,生成下一个词。
  4. 重复这个过程,直到生成结束符,或者达到最大长度。

推理的时候,因为是自回归的,不能完全并行,所以推理速度比训练慢一些。但可以用一些优化方法,比如KV缓存,把之前计算的Key和Value缓存起来,不需要每次都重新计算,大大提升推理速度。

六、Transformer为什么这么强大?

最后,总结一下,Transformer为什么这么强大,为什么能取代RNN,成为深度学习的主流架构。

1. 并行计算,训练速度快

RNN是按顺序处理的,一个词一个词地算,不能并行,训练速度慢。而Transformer的自注意力,是对整个序列并行计算的,所有词同时算,训练速度快很多,尤其是在长序列的情况下,优势更明显。

2. 长距离依赖,捕捉能力强

RNN处理长序列的时候,前面的信息,经过很多步的传递,容易丢失,长距离依赖的捕捉能力差。而Transformer的自注意力,每个词都能直接关注到序列中的所有词,不管距离多远,都能直接建立联系,长距离依赖的捕捉能力很强。

3. 表达能力强,可扩展性好

Transformer的多头注意力、前馈网络、残差连接、层归一化等设计,让它的表达能力很强,而且可以通过增加层数、增加维度、增加头数,很方便地扩展模型规模。后来的大语言模型,比如GPT-3、LLaMA、ChatGPT等,都是基于Transformer,通过扩大模型规模,获得了强大的能力。

4. 通用性强,适用范围广

Transformer最初是为自然语言处理设计的,但后来人们发现,它的架构很通用,可以用到很多领域,比如计算机视觉、语音识别、多模态、蛋白质结构预测等,都取得了很好的效果。这种通用性,让Transformer成为了一个通用的深度学习架构,也让它的影响力越来越大。

七、写在最后

Transformer,是深度学习领域的一个里程碑式的架构,它彻底改变了自然语言处理,也影响了整个AI领域。理解Transformer的原理,对于学习深度学习和AI,是非常重要的。

今天,我们从注意力机制、自注意力、多头注意力、位置编码、编码器、解码器、训练推理等方面,深入剖析了Transformer的架构原理。希望通过这篇文章,大家能对Transformer有一个更深入、更全面的理解。

当然,Transformer的内容,远不止这些,还有很多细节和变种,比如BERT的双向编码器、GPT的解码器-only架构、T5的编码器-解码器、ViT的视觉Transformer、各种位置编码、各种注意力优化等,都值得深入学习。但理解了原始Transformer的基本原理,再学习这些变种,就会容易很多。

AI的发展日新月异,新的模型和架构层出不穷,但Transformer,依然是当前AI的基石。理解了Transformer,就理解了当前AI的核心。

希望这篇文章,能对大家有所帮助。如果有什么问题或者不同的看法,欢迎在评论区交流。