Transformer详解


1.Introduction

Transformer 是一个完全基于自注意力机制(Self-Attention)的编解码器模型,它摒弃了传统的 RNN 和 CNN,通过多头注意力捕捉序列的全局依赖关系,并利用前馈神经网络进行特征变换,辅以残差连接层归一化来保证深层网络的稳定训练。

1.Transformer 到底解决了什么痛点?

  • 传统 RNN 的致命弱点:串行计算与遗忘。 RNN 必须逐字阅读(例如先处理“我”,再处理“爱”,再处理“中”……)。这种串行机制导致两个致命问题:一是无法并行加速(GPU 都在闲置等待);二是长距离依赖问题(读到句子末尾时,早把句子开头的细节忘光了)。
  • Transformer 彻底抛弃了“从左到右”的顺序读取机制。它如同一个“上帝视角”,一次性把整个句子吞进去。无论两个词相隔多远,它们之间的距离永远是 1 步。这种设计不仅让 GPU 可以火力全开(并行计算),还完美解决了长距离信息丢失的问题。

2.宏观架构:Encoder-Decoder(编码器-解码器)

原始的 Transformer 被设计用来做机器翻译,因此它采用的是经典的 Encoder-Decoder 架构。我们可以把它想象成一个极度高效的翻译团队:

编码器(Encoder):负责“理解”

  • 输入: 源语言(比如一段中文)。
  • 任务: 深入理解这句话的语法、语义、指代关系,将其提炼成一个高度浓缩的、包含所有上下文信息的稠密矩阵。
  • 特点: 它里面的所有词都可以互相看到彼此(这叫双向注意力)。BERT 就是一个纯 Encoder 架构。

解码器(Decoder):负责“生成”

  • 输入: Encoder 提炼的“中间语言” + 已经翻译出来的部分词汇。
  • 任务: 根据这些信息,像挤牙膏一样,一个字一个字地生成目标语言(比如英文)。
  • 特点: 在生成第 $N$ 个词时,它只能看到前 $N-1$ 个词,不能偷看未来的词(这叫掩码注意力 Masked Attention)。如今火爆的 GPT 系列,就是一个纯 Decoder 架构。

2. 输入层-词嵌入&位置编码

1. 词嵌入(Word Embedding):给文字分配“坐标”

在 Transformer 真正开始工作之前,必须先过语言转换这一关,因为计算机只认识数字。

  • 分词与映射: 首先将句子切分成一个个 Token(词或字),然后去词表中查表,把它映射成一个高维的稠密向量(在原论文中,这个维度是 $d_{model} = 512$)。

  • 核心直觉: 你可以把这 512 维想象成一个有 512 个坐标轴的超高维空间。在这个空间里,“语义相近”的词,它们的物理距离就越近(比如“苹果”和“橘子”靠得很近,但离“汽车”就很远)。

2.位置编码(Positional Encoding):解决“词序失忆症”

  • 原因: 我们在上一节提到,Transformer 的核心优势是“一次性全局并行处理”。但这也带来了一个致命缺陷:Self-Attention 本身是没有位置感的(它是置换不变的)

  • 例子: 在原始的自注意力机制眼里,“狗咬人”和“人咬狗”算出来的结果是一模一样的,因为它只看词和词之间的相关性,完全不管谁在前谁在后。

  • 解法: 既然模型自己看不出顺序,我们就必须人为地把位置信息“刻”在词向量里,再喂给模型。这就好比给参加会议的每个人不仅发了名牌(词嵌入),还发了座位号(位置编码)。

3. 位置编码的数学原理

核心公式:
假设我们要为位置 $pos$ 的词生成一个 512 维的位置向量,它的第 $i$ 个维度($i$ 从 0 到 255)的值由以下公式计算:

其中:

  • $pos$ 是词在句子中的绝对位置(比如第 0 个词,第 1 个词)。
  • $2i$ 和 $2i+1$ 代表向量中的偶数维度和奇数维度。
  • $d_{model}$ 是向量的总维度(如 512)。
  • 它能让模型轻松学习到相对位置信息。根据三角函数的和差化积公式:这意味着,位置 $pos + k$ 的编码,可以通过位置 $pos$ 的编码进行线性变换得到。这对模型理解“词 A 在词 B 后面 3 个位置”这种相对关系极其重要。

想象一个有 512 个指针的钟表:

  • 低维度($i$ 很小): 分母接近 1,正余弦函数的频率很高。就像秒针,位置稍微变一点($pos$ 加 1),它的值就剧烈变化。这帮模型区分相邻的词。
  • 高维度($i$ 很大): 分母非常大(接近 10000),函数的频率极低。就像时针,走得很慢。这帮模型感知长距离的宏观位置。

4.常见问题

Q:为什么要用三角函数?直接用 0, 1, 2, 3 作为位置编号不行吗?
  • 不行。如果用整数,句子越长,位置数值就越大。这会导致模型在处理长句子时,后面的位置编码数值把词嵌入原本的语义信息“淹没”掉,并且模型难以泛化到比训练集更长的句子。
  • 而三角函数的值域永远被限制在 $[-1, 1]$ 之间,非常稳定。
Q:输入层是把词嵌入和位置编码相加(Add),为什么不是拼接(Concat)?
  • 拼接会增加模型的维度,导致参数量和计算量翻倍。
  • 至于为什么“相加”不会造成信息混乱?因为在一个极高维(如 512 维)的空间中,词嵌入向量和位置编码向量几乎是近似正交的。正交的向量相加,就像在 $x$ 轴的信息上加了 $y$ 轴的信息,彼此其实互不干扰。
为什么位置编码有效
1. 物理直觉:信号的“叠加”与“解耦”

想象一下你在听一首交响乐。

词嵌入(Word Embedding): 就像是小提琴拉出的旋律(语义)。

位置编码(Positional Encoding): 就像是背后极其规律的架子鼓节拍(位置)。

在空气中传到你耳朵里时,这两个声音的物理声波是直接相加(叠加)的。但你的大脑会把它们混淆成一种“非琴非鼓”的怪声吗?不会。你的大脑依然能清晰地分辨出旋律是什么,节拍在哪个位置。

在神经网络中,只要这两个信号的“频率”或“特征”差异足够大,后续的线性层(可以理解为极其高级的滤波器)就能轻松把它们分离开来。

2. 空间几何:高维空间的“正交性”

我们在纸上画图习惯了二维或三维空间,但在 Transformer 中,这是一个 512 维的超高维空间。高维空间有一个非常反直觉的数学特性:任意两个独立生成的向量,大概率是近似正交(互相垂直)的。

  • 正交意味着互不干扰: 假设在二维平面上,词向量对应 $X$ 轴的信息 $(x, 0)$,位置向量对应 $Y$ 轴的信息 $(0, y)$。把它们相加得到 $(x, y)$。
  • 在这个结果里,$X$ 轴的投影依然是纯粹的语义,$Y$ 轴的投影依然是纯粹的位置。它们在同一个载体里,但彼此透明,互不遮挡。
3. 数学证明

假设我们有两个词,词 $i$ 的输入是 $x_i = E_i + P_i$,词 $j$ 的输入是 $x_j = E_j + P_j$。在 Self-Attention 中,它们会分别乘以权重矩阵变成 $Q$ 和 $K$,然后做点积求相似度。为了简化问题,我们直接看原始输入向量的点积:

利用乘法分配律,我们可以把它展开成四项:

本来是揉成一团的加法,在经过点积运算后,自动解耦成了四种纯粹的交互:

  1. $E_i \cdot E_j$: 纯看这两个词的语义搭不搭(比如“苹果”和“吃”分很高)。
  2. $P_i \cdot P_j$: 纯看这两个词的物理距离近不近(比如位置 3 和位置 4 分很高,位置 3 和位置 100 分很低)。
  3. $E_i \cdot P_j$ 与 $P_i \cdot E_j$: 这两项通常被认为是交叉噪声,而且因为前面提到的“正交性”,这两项的值通常在 0 附近徘徊。

结论: 简单的相加,不仅省去了拼接带来的显存翻倍,而且在后续的乘法(Attention)运算中,能够自然而然地被模型“拆解”出各自的价值。模型通过训练 $W^Q$ 和 $W^K$ 矩阵,会主动放大第一项和第四项,抑制交叉项。

真实的注意力得分计算是 $Q_i \cdot K_j$,只看位置编码这部分的话,实际上是:

用矩阵转置的性质,可以写成:

只要中间夹着的这个矩阵 $M = W^Q (W^K)^T$ 不是一个对称矩阵(在神经网络通过反向传播随机学习的过程中,它极大概率不是对称的),那么:

所以,原生的绝对位置编码(Sine/Cosine)本身确实是“不辨方向”的,只能提供距离感。方向感(前后关系)是依靠注意力机制中 $W^Q$ 和 $W^K$ 这两个不对称的权重矩阵,在模型训练过程中“学”出来的。 这也是为什么后来很多更先进的大模型(比如采用 RoPE 旋转位置编码的模型)要改进位置编码,因为 RoPE 直接在数学层面就把“方向性”内嵌进去了,不需要完全依赖模型去“死记硬背”,从而表现得更加优雅和高效。

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

1. 什么是 $Q$、$K$、$V$

  • $Q$ (Query / 查询向量): 这是你手里拿着的搜索框里的关键词。它代表着:“我想寻找什么样的信息来补充我自己?”
  • $K$ (Key / 键向量): 这是图书馆里每本书书脊上的标签/书名。它代表着:“我包含了什么样的信息?”
  • $V$ (Value / 值向量): 这是书里面真正的正文内容。它代表着:“如果我的标签 ($K$) 匹配了你的搜索 ($Q$),你可以把我里面的内容 ($V$) 拿走。”

2. Self-Attention 的四个数学步骤

假设我们的输入是一个矩阵 $X$(包含了句子中所有词的词嵌入+位置编码)。

第一步:生成 $Q, K, V$

输入矩阵 $X$ 分别乘以三个不同的权重矩阵 $W^Q$、$W^K$、$W^V$(这三个矩阵是模型在训练过程中要学习的核心参数),映射出三个新矩阵:

第二步:计算注意力得分(打分)

词要想知道自己该关注谁,需要拿自己的 $Q$ 去和所有词的 $K$ 计算相似度。在数学上,两个向量越相似,它们的点积(Dot Product)就越大。

这个操作会得到一个 $N \times N$ 的方阵($N$ 是序列长度)。例如,矩阵第 $i$ 行第 $j$ 列的数值,就代表了“词 $i$ 对词 $j$ 的关注程度”。

第三步:缩放与归一化(把分数变成百分比)

为了防止点积的结果过大(这会导致反向传播时梯度消失),我们需要除以一个缩放因子 $\sqrt{d_k}$($d_k$ 是 $K$ 向量的维度)。

当维度 $d_k$ 很大时,两个独立分布的向量做点积,其结果的方差会随着维度 $d_k$ 变大而变大,导致点积值极大或极小。极大的值送入 $\text{softmax}$ 后,会把概率分布推向绝对的 $0$ 或 $1$,使得进入了 $\text{softmax}$ 的饱和区(平坦区)。此时梯度几乎为 $0$(梯度消失),模型根本无法更新。除以 $\sqrt{d_k}$ 就是为了把点积结果的方差强行拉回 $1$,保证梯度平稳。

然后再套上一个 $\text{softmax}$ 函数,把所有的分数转化成 $0 \sim 1$ 之间的概率分布,并且保证每一行的和为 1。

第四步:加权求和(提取信息)

现在,我们知道了每一个词应该对其他词分配多少注意力比例(权重)。最后一步,就是用这些权重去乘以它们对应的真正内容 $V$。

出来的结果,就是一个融合了全局上下文信息的全新矩阵!在这个新矩阵里,“苹果”这个词的向量,不仅包含了它自己的本意,还悄悄融合了“吃”和“红色”的特征。

4. 结构

在原论文中,Transformer 是一个用于机器翻译的 Encoder-Decoder(编码器-解码器) 架构。两边都由 $N=6$ 个相同的模块(Block)堆叠而成。

编码器模块(Encoder Block)

它就像一个流水线车间,只做两件事:特征提取与特征融合。每个 Block 包含两个子层:

1.Multi-Head Self-Attention(多头自注意力): 让句子里的词互相交流,提取全局上下文。

2.Feed Forward Network (FFN / 前馈神经网络): 这是一个两层的全连接网络(通常中间用 ReLU 或 GELU 激活函数)。它只对单个词的向量进行局部的非线性映射。

Attention 负责“词与词之间的信息交流”,FFN 负责“词自身的特征升维与提炼”。

解码器模块(Decoder Block)

解码器比编码器多了一个关键部件,它有三个子层:

1.Masked Multi-Head Self-Attention(掩码多头自注意力): 解码器在生成文本时,只能看之前的词,不能“偷看”未来的词。

2.Cross-Attention(交叉注意力): 这是 Encoder 和 Decoder 握手的地方!在这里,$Q$ 来自解码器上一层的输出(表示“我当前生成到哪了,我需要什么信息”)。$K$ 和 $V$ 来自编码器的最终输出(表示“源语言的全部特征”)。
3.Feed Forward Network (FFN): 作用同上。

Add & Norm

1.Add (残差连接 / Residual Connection)

公式:$Output = x + \text{Sublayer}(x)$。为了解决网络加深后的梯度消失问题,保证底层信息能直接短路传到高层。

2.Norm (层归一化 / Layer Normalization)

为啥要用层归一化
1. 为什么要“归一化”?

在深度神经网络中,随着层数的加深,每一层的数据分布都在不断变化(这在学术上叫 Internal Covariate Shift,内部协变量偏移)。

  • 痛点: 想象一下,上一层传过来的数据,一会儿在 $[0, 1]$ 徘徊,一会儿又飙升到 $[-1000, 1000]$。下一层的神经元就会彻底“懵圈”,为了适应这种剧烈波动的输入,它不得不拼命调整自己的权重。这会导致梯度忽大忽小,模型极难训练,甚至直接崩溃(梯度爆炸/消失)。
  • 归一化的作用: 强行把每一层的数据分布拉回到一个稳定的标准状态(通常是均值为 0,方差为 1 的正态分布)。这就像是给神经元戴上了“防抖云台”,让数据平稳地向后传递。
2. LayerNorm 的数学原理

LayerNorm 的核心思想是:对某一个具体的词向量(Token),在它的所有特征维度上进行归一化。

假设我们有一个维度为 $H$(比如 512)的词向量 $x = [x_1, x_2, \dots, x_H]$。

LayerNorm 的计算分为三步:

第一步:计算该词向量内部的均值和方差

第二步:标准化(减去均值,除以标准差)

(注:$\epsilon$ 是一个极小的常数,如 $1e-5$,纯粹是为了防止分母为 0 导致报错。)

第三步:仿射变换(极其关键!)

标准化虽然让数据稳定了,但也强行破坏了网络好不容易学到的特征表达。为了弥补这一点,LayerNorm 引入了两个可学习的参数:缩放因子 $\gamma$(Gamma)和偏置 $\beta$(Beta)。

网络在训练过程中,如果发现“强行拉回标准正态分布”效果不好,它可以通过学习 $\gamma$ 和 $\beta$ 把数据分布再变回去。这相当于给网络留了一条退路,保证了模型的表达能力。

LayerNorm vs BatchNorm

我们可以用一个极其直观的“考试分数”比喻来区分它们: 假设有一个班级(Batch Size),学生考了多门课(特征维度 $H$)。

  • BatchNorm (BN): 像是在算某一门课的年级排名。把全班所有人的“数学成绩”拉出来算均值和方差。
    • CV最爱: 图片大小固定,像素特征对齐,非常适用。
    • NLP的噩梦: 句子的长度参差不齐!你的第 3 个词是动词,我的第 3 个词是标点,强制把它们放一起算均值毫无物理意义。而且 Batch Size 太小时,BN 计算的方差极其不准。
  • LayerNorm (LN): 像是在算某一个学生的总成绩水平。只看张三这一个学生,把他自己的“语数外物化生”所有成绩加起来算均值和方差。
    • NLP 的救星: 它完全不受 Batch Size 大小的影响,也不受句子长度变化的干扰(不管句子多长,每个词都是独立计算自己的归一化)。因此它是 Transformer 的绝配。
Pre-Norm vs Post-Norm
  • 原版的 Transformer 论文使用的是 Post-Norm(后归一化),结构是 x + Sublayer(x) 然后再做 LayerNorm。但这种方式在网络叠得很深时,梯度极不稳定,经常导致训练崩溃(Warmup 策略就是为了强行救场)。
  • 现在的 LLM(如 GPT 系列、LLaMA 等)几乎全部换成了 Pre-Norm(前归一化)。结构变成了 x + Sublayer(LayerNorm(x))。数据先经过归一化再进入注意力层,残差支路保持绝对的干净,这使得深层网络极其稳定,甚至不用 Warmup 也能练。
RMSNorm

RMSNorm(均方根归一化)是 LayerNorm 的一种“青春版”。它认为 LayerNorm 真正起作用的是“除以方差”来缩放尺度,而“减去均值”做平移其实没什么卵用,反而拖慢了计算速度。因此,RMSNorm 直接砍掉了减均值的步骤,只保留方差缩放,既保证了效果,又提升了 10%~50% 的计算效率。

To be continued


Author: YANG
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source YANG !
  TOC