Transformer 架构学习笔记

背景

2017 年,Google 团队发表了论文《Attention Is All You Need》,首次提出了 Transformer 架构。该架构完全基于 自注意力机制(Self-Attention),摒弃了传统的循环神经网络(RNN)或卷积神经网络(CNN),成为后续大模型(如 BERT、GPT 等)发展的基础。


1. Transformer 之前,如何处理自然语言?

1.1 前馈神经网络(FNN)

架构图:
[image: FNN 处理自然文本的流程]

示例输入:水是有毒的
在这里插入图片描述

什么是合并词向量?
由于 FNN 要求输入是固定长度的(不能像 RNN 那样逐个输入词),所以需要把这 4 个向量合并成一个向量。
两种常见合并方式:

平均(Average):将 4 个向量的每个维度分别求平均值,得到一个新向量。
例如第一个维度:(0.2 + 0.0 + 0.9 + 0.1) / 4 = 0.3,依此类推。
缺点:完全丢失了词的顺序信息(“水有毒”和“有毒水”会被当成一样的)。

拼接(Concatenation):将 4 个向量首尾连接成一个更长的向量。
例如 4 个 4 维向量拼接成 1 个 16 维向量。

FNN 的缺点

  • 无法理解词语顺序,缺乏上下文建模能力
  • 输入维度固定,句子长度变化时无法处理(比如 3 个词和 5 个词的句子拼接后维度不同)。

1.2 循环神经网络(RNN)

RNN 的优势

  • 按时间顺序(token 顺序)处理输入,建模词序
  • 具有"记忆"机制,建模上下文依赖
  • 支持不定长输入

计算过程

在这里插入图片描述

  • W, U, V:权重矩阵
  • h0:初始隐藏状态
  • g:激活函数

以h1计算过程为例

		h1 = g(t1 * W + U * h0)
		y1 = g(h1 * V)

至此,我们通过计算,得到了两个输出,分别是 h1 和 y1,
其中,y1是我们需要翻译的结果I,
h1则是携带了上一步的token信息,参与下一步的计算。

RNN 的局限

  • 输入输出长度必须相等(如"我爱水课" → “I love water class”)

1.3 编码器-解码器结构(Encoder-Decoder)

RNN解决了输入不定长问题,但是没能解决输入和输出不等长的问题。
为了解决输入输出不等长的问题,将输入和输出拆开我们就得到了编码器 - 解码器结构, 如图所示
在这里插入图片描述

什么是上下文向量 C

它是对整个输入序列的语义编码,是一个固定长度的向量,涵盖了整个输入文本的语义信息。
最简单的编码方式:C = 最后一个时间步的隐藏状态输出(h4)
它将作为 Decoder 的输入,用于生成目标序列。

优点

  • 编码器和解码器职责分离
  • 输入信息被编码为固定长度的上下文向量 C

缺点

  • 上下文向量c 多次解码,可能导致上下文向量c的信息被稀释,导致后续计算不准确。

改进:让上下文向量C参与每一步的解码过程

[image: 改进后的编码器-解码器结构]
改进后,解码器的每一步都会重新参考同一个上下文向量 C,相当于每一步都在问:“我刚才读到的输入信息是什么?”
这在一定程度上缓解了信息稀释的问题。

但仍未解决的核心问题:遗忘问题(Long-Term Forgetting)

即使让 C 参与每一步,它仍然是一个固定长度的向量
当输入句子很长时(比如一篇 1000 字的文章),C 必须把所有信息压缩成有限长度的向量,这会导致:

  • 早期输入的信息(如句首的关键词)在压缩过程中被“挤掉”
  • 距离较远的依赖关系(如第 1 个词和第 500 个词之间的关系)很难被 C 完整保留
  • 解码器越往后生成,对输入开头的“记忆”越模糊

1.4 注意力机制(Attention Mechanism)

解决的问题

  • 长序列中的"遗忘"问题
  • 不同时间步对当前输出的重要性不同

核心思想

  • 为每个时间步的输入分配不同权重
  • 上下文向量 C 是加权和:

结构如下:
在这里插入图片描述

计算过程:
在计算C0的时候,我们给h1的权重更高,让模型更能关注到“我”这个信息。
在计算C1的时候,我们给h2更高的权重,让模型更能关注到“爱”这个信息,如下图所示:
在这里插入图片描述


1.5 小结:Transformer 之前的序列转导模型

  • 基于 RNN / CNN
  • 使用编码器-解码器结构
  • 引入注意力机制增强

需要说明的是,注意力机制在 Transformer 架构提出之前就已经存在。
到此为止,模型其实已经能够较好地处理上下文和位置关系。

但为什么 AI 还没有迎来爆发?

核心原因在于:上述所有模型(RNN、LSTM、带注意力的 Encoder-Decoder)都是串行计算的。

  • 每一步计算都必须依赖前一步的输出结果
  • 无法并行处理,训练速度极慢
  • 难以在工程层面进行大规模扩展

串行计算成为了真正的性能瓶颈,而非模型表达能力。


2. Transformer 架构

核心特点

  • 完全摒弃 RNN / CNN
  • 仍使用编码器-解码器结构
  • 完全基于注意力机制

2.1 整体结构

[image: Transformer 整体结构图]


2.2 计算过程

以"我爱水课"为例

  1. 获取文字的矩阵信息(Embedding)
  2. 使用傅里叶变换(位置编码)获取位置信息
  3. 叠加得到 1×512 的矩阵,包含文字和位置信息
    在这里插入图片描述

这里叠加可以理解成两个矩阵的加法,得到的新矩阵同时包含语义和位置信息。

2.3 自注意力机制(Self-Attention)—— 核心基础

在介绍多头注意力之前,必须先理解 单头自注意力 是如何工作的。

2.3.1 为什么要用自注意力?

之前我们得到每个词的 1×512 矩阵,包含了:

  • 词本身的语义信息(Embedding)
  • 位置信息(Positional Encoding)

但缺少了上下文信息,比如:

  • “水” 和 “有毒” 之间的关系
  • “我” 和 “爱” 之间的动作关系

自注意力机制的目的:让每个词都“看到”句子中的所有其他词,并计算出它们之间的相关性权重

2.3.2 Q、K、V 是什么?

对于输入矩阵 X(形状 n × 512,n 是句子长度),我们通过三个不同的权重矩阵 W_QW_KW_V(每个都是 512 × 512)分别计算得到三个新矩阵:
在这里插入图片描述

  • Q(Query,查询)Q = X · W_Q,代表“当前词想查询什么”
  • K(Key,键)K = X · W_K,代表“每个词能提供的标签”
  • V(Value,值)V = X · W_V,代表“每个词实际携带的信息”

形象理解:

  • Query 相当于你在搜索引擎里输入的“问题”
  • Key 相当于网页的“标题/关键词”
  • Value 相当于网页的“正文内容”
    通过匹配 Query 和 Key,决定从 Value 中取多少信息。
2.3.3 注意力权重计算(Scaled Dot-Product Attention)

步骤 1:计算注意力分数

用 Q 和 K 做点积,得到一个 n × n 的分数矩阵:

我们通过Q和K的点积计算,并进行归一化的处理,就得到了每个单词在这句话中的权重。计算公式如下:
在这里插入图片描述
其中:

  • 分子部分:表示第 i 个词对第 j 个词的关注程度(未归一化)
  • 分母部分:除以 √d_k(d_k 是 K 的维度,这里为 512),防止点积结果过大导致梯度消失
  • Softmax 归一化:对每一行做 Softmax,得到 注意力权重矩阵 Attention_Weights(形状 n × n),每行之和为 1
  • 加权求和:用归一化后得到的权重矩阵,乘以 V, 得到最终的上下文表示
2.3.4 一个具体例子

句子:“我 爱 水课”

  • 计算 “爱” 对 “我”、“爱”、“水课” 的注意力分数
  • 可能得到:[0.2, 0.7, 0.1](“爱” 最关注自己,其次关注 “我”)
  • 然后用这个权重去加权 V 中的信息,得到 “爱” 的新表示,这个表示中,包含了完整的句子信息(语义+位置),还包含了每个词对其它词的关注度(权重)。

结果:每个词的输出向量都 融合了整个句子的上下文信息

2.4 多头注意力机制(Multi-Head Attention)

有了单头自注意力的基础,我们再来理解多头注意力。

2.4.1 为什么需要多个头?

单头注意力只能学习 一种相关性模式,例如:

  • 可能只关注相邻词
  • 可能只关注句首句尾

但真实语言中,一个词可能同时存在多种关系:

  • “苹果” 可能既和 “吃” 有动作关系
  • 又和 “水果” 有类别关系
  • 还可能和 “公司” 有品牌关系

多头注意力的做法

  • 将 Q、K、V 分别切分成 h 份(例如 8 个头,每个头维度 512/8 = 64)
  • 每个头独立计算自注意力
  • 每个头可以学习 不同的注意力模式
2.4.2 计算过程
  1. 将 Q、K、V 分别拆成 h 个低维矩阵(每个维度 n × 64
  2. 每个头独立执行单头注意力:
  3. 将所有头的输出拼接(Concat)回 n × 512
  4. 通过一个线性层 W_O512 × 512)融合多头信息
    在这里插入图片描述
2.4.3 多头注意力的优势
  1. 增强表达能力:每个头学习不同的注意力模式
  2. 参数效率与并行性:拆分为多个头并行计算,充分利用 GPU
  3. 梯度更稳定:小维度(64)计算更稳定
  4. 允许模型“分而治之”:不同头专注不同子任务
2.4.4 为什么最后还需要一个线性层?

多头输出只是简单拼接,不同头的特征是并列的、没有交互。
通过 W_O 线性层,让不同头的信息 加权融合,形成统一的表示。

2.5 小结:Transformer 如何解决串行计算问题?

在 RNN 中:下一步计算必须等上一步完成(串行)
在 Transformer 中:

  • 输入是一次性全部传入的
  • 自注意力通过矩阵运算 Q·K^T 一次性计算出所有词对之间的权重
  • 得到一个 n × n 的注意力矩阵,包含了完整的:
    • Token 信息
    • 位置信息
    • 上下文信息
    • 注意力权重

这就是 Transformer 能够并行计算的核心原因。


2.6 残差连接(Residual Connection)

简单来说,残差连接就是把层的输入直接“跳过”该层,加到输出上。
这样做可以缓解信息在多层传递中被稀释的问题,让模型训练更稳定。

本文不再展开,感兴趣可自行查阅相关资料。

2.7 带掩码的多头注意力(Masked Multi-Head Attention)

这是解码器(Decoder)中使用的一种注意力机制,目的是在生成当前位置的输出时,屏蔽掉未来的信息,防止“提前看到答案”。

由于本文定位为入门介绍,此处不再深入讲解。


结语

本文主要梳理了 Transformer 的核心思想与关键组件,重点介绍了从 RNN/CNN 到注意力机制的演进过程,以及自注意力与多头注意力的基本原理。
更深入的内容(如掩码机制、Feed-Forward Network、Layer Norm 等)暂不展开,感兴趣的读者可结合论文《Attention Is All You Need》或相关视频进一步学习。

参考资料
感谢 B站 UP主“读论文的小羊”提供的视频讲解,本文内容参考自该视频,特此致谢!
视频链接:https://www.bilibili.com/video/BV1XEanzkEAm/

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐