
1. 从“黑盒”到“透明”为什么我们需要关注Transformer的数据流动如果你和我一样在刚接触Transformer模型时被一堆“多头注意力”、“前馈网络”、“LayerNorm”这些术语砸得晕头转向然后对着论文里的架构图看了半天感觉每个模块都懂了但连起来就不知道数据到底是怎么“流”过去的那么这篇文章就是为你写的。我们看过太多文章在拆解Transformer的各个部件像介绍汽车零件一样告诉你这是发动机Self-Attention那是变速箱FFN。但很少有人像修车师傅一样带你打开发动机盖指着说“看汽油输入数据从这里进来经过化油器Embedding混合在气缸Attention Heads里爆炸做功动力通过传动轴残差连接输出同时还有废气再循环Add Norm来稳定燃烧。”这就是“数据流动”视角的独特价值。它不满足于知道零件叫什么而是要弄清楚能量信息在系统里是如何传递、转换和汇聚的。对于Transformer这样一个彻底抛弃了CNN的局部归纳偏置和RNN的时序递归结构的模型理解其数据流动是理解它为何强大的关键。你会发现所谓的“注意力机制”只是一个精巧的算子而Transformer真正的骨架是那一套严谨的、可堆叠的数据流图。通过追踪一个词向量从输入到输出的完整旅程我们不仅能透彻理解Encoder-Decoder架构更能看清如今大行其道的Decoder-Only架构如GPT系列和Encoder-Only架构如BERT本质上是如何对这套数据流进行裁剪和特化的。这比单纯记忆公式要有用得多。2. 旅程的起点输入数据的“预处理车间”任何数据的旅程都始于准备阶段。对于Transformer尤其是处理自然语言时这个阶段的目标是把离散的、符号化的文本转换成连续的、富含语义信息的数值向量并告诉模型这些符号在序列中的“位置”。2.1 词嵌入从符号到向量的映射假设我们的输入句子是“I love AI”。模型看到的首先是一串索引比如[101, 102, 103]假设的token ID。词嵌入层Embedding Layer就是一个巨大的查找表其每一行对应一个词或子词的向量表示。这个查找表是可学习的参数矩阵。数据流动细节输入一个形状为[batch_size, sequence_length]的整数张量每个位置是一个token ID。操作嵌入层执行一次“查表”操作。对于ID为i的token它取出嵌入矩阵的第i行。输出一个形状为[batch_size, sequence_length, embedding_dim]的浮点数张量。此时“I”、“love”、“AI”这三个孤立的符号变成了三个embedding_dim维的向量例如d_model512。你可以把它们想象成三个在512维空间中的点。注意这个初始向量是“静态”的同一个词在任何句子、任何位置其初始向量都一样。它编码了词汇的“字典意义”但还没有上下文信息。2.2 位置编码为向量注入“顺序感”RNN和CNN通过其结构天然地感知顺序或位置。Transformer的注意力机制是“全连接”的本身是位置无关的Permutation Invariant。打乱输入序列的顺序注意力计算的输出在集合意义上是等价的。这显然不符合语言特性。因此必须显式地注入位置信息。为什么是“加法”而不是“拼接”这是理解数据流的一个关键点。常见的位置编码如原始论文的正余弦编码与词嵌入向量相加而不是拼接。相加output token_embedding position_embedding。这相当于在同一个语义空间里对词向量进行了一个与位置相关的平移。信息在同一个通道内融合。拼接output concat([token_embedding, position_embedding])。这会改变向量的维度例如从512维变成5125121024维增加了后续线性变换的参数负担且融合方式不如加法直接。数据流动细节生成根据每个token在序列中的位置pos0, 1, 2...和向量维度索引i通过公式如正余弦函数计算出一个值构成位置编码向量PE(pos)。融合combined_embedding token_embedding PE(pos)。这是一个逐元素的加法操作。输出形状仍为[batch_size, sequence_length, embedding_dim]但此时每个向量都同时包含了“我是谁”词汇语义和“我在哪”序列位置的信息。经过这个“预处理车间”原始的符号序列就变成了一个富含初步信息的数值矩阵准备进入Transformer的核心加工流水线。3. Encoder的数据流水线信息的多轮提炼与聚合Encoder的目标是为输入序列中的每个token生成一个融合了整个序列所有token上下文信息的新的表示。这个过程不是一步到位的而是通过多个相同的层Layer堆叠进行多轮迭代式提炼。每一层的数据流都遵循相同的模式但处理的信息层次越来越抽象。3.1 单层Encoder的核心数据流图每一层Encoder都由两个核心子层构成数据流严格遵守以下路径这是Transformer稳定训练和高效学习的基石输入X -- 子层1: 多头自注意力 (Multi-Head Self-Attention) -- 操作A: 残差连接 (Add) -- X Attention(X) X 操作B: 层归一化 (LayerNorm) -- Y LayerNorm(X) -- 子层2: 前馈网络 (Feed-Forward Network) -- 操作C: 残差连接 (Add) -- Y FFN(Y) Y 操作D: 层归一化 (LayerNorm) -- 输出Z LayerNorm(Y)让我们拆解这个流图中的每一个环节。3.1.1 多头自注意力全局信息交换大会这是信息聚合的核心环节。输入序列的每个token向量通过这个机制与序列中所有其他token向量进行“交流”根据相关性加权汇总信息。数据流动详解线性投影生成Q, K, V对于输入矩阵X形状[batch, seq_len, d_model]我们分别用三个不同的可学习权重矩阵W_Q,W_K,W_V进行线性变换得到查询Query、键Key、值Value矩阵。Q X * W_Q,K X * W_K,V X * W_V为什么这么做这相当于让每个token化身三种角色Q代表它“想知道什么”K代表它“能提供什么”V才是它“实际的内容”。投影是为了让模型学习在不同语义子空间中进行匹配和提取。分头计算“多头”意味着将d_model维的Q, K, V在最后一维上切分成h份例如h8则每头维度d_k d_model / h 64。每一份数据独立进行后续的注意力计算。为什么分头类比于卷积神经网络的多通道滤波器每一头可以关注不同方面的关系例如语法、语义、指代等。并行计算提高了效率也增强了模型的表示能力。缩放点积注意力计算这是每个注意力头内的核心操作。计算注意力分数Scores (Q_head * K_head^T) / sqrt(d_k)。Q * K^T计算了每对token之间的相关性点积相似度sqrt(d_k)是为了在维度较高时防止点积结果过大导致Softmax梯度消失。归一化与加权Attention_weights Softmax(Scores, dim-1)。Softmax沿着最后一个维度键的维度进行使得每个token对所有token的注意力权重之和为1。聚合信息Output_head Attention_weights * V_head。每个token的新表示是所有token值的加权和权重就是它与其它token的相关性。多头输出合并将h个注意力头的输出矩阵形状[batch, seq_len, d_k]在最后一维拼接起来恢复为[batch, seq_len, d_model]的形状。最终线性投影通过一个可学习的权重矩阵W_O对拼接后的结果进行线性变换得到自注意力子层的最终输出。这一步是为了整合来自不同注意力头的信息并可能进行维度调整。3.1.2 残差连接与层归一化训练稳定性的守护神这是数据流中确保梯度有效流动、加速训练的关键设计。残差连接Add将子层的输入X直接加到子层的输出F(X)上得到X F(X)。为什么有效它创建了一条从输入到输出的“高速公路”让梯度可以直接回传极大缓解了深层网络中的梯度消失/爆炸问题。它隐含的假设是每个子层只需要学习对输入的“残差”修改F(X)而不是完整的映射这使优化变得更容易。层归一化LayerNorm对每个样本的每个位置的特征向量进行归一化即对d_model维度求均值和方差然后进行缩放和平移。公式LayerNorm(x) γ * (x - μ) / σ β其中μ, σ是x的均值和标准差γ, β是可学习的参数。与BatchNorm的区别BatchNorm是对一个Batch内所有样本的同一特征维度进行归一化在序列长度变化时不稳定。LayerNorm对单个样本的所有特征进行归一化与Batch大小无关更适合NLP任务。在数据流中的位置注意原始论文和普遍实现采用的是“Post-LN”结构即LayerNorm(X Sublayer(X))。现在也有研究采用“Pre-LN”即X Sublayer(LayerNorm(X))后者通常能使训练更稳定。但无论如何Add Norm 的组合构成了一个稳定的“模块”让数据在流经非线性变换后分布不会发生剧烈偏移。3.1.3 前馈网络每个位置的独立“深度加工”经过注意力机制聚合了全局信息后前馈网络FFN对每个位置的特征进行独立的、非线性的变换。结构通常是一个两层的全连接网络中间包含一个激活函数如ReLU或GELU。FFN(x) max(0, xW1 b1)W2 b2。其中中间层的维度通常比d_model大例如4*d_model因此FFN也被称为“位置级全连接前馈网络”。数据流动输入形状[batch, seq_len, d_model]FFN对第二个维度seq_len的每一个位置独立地进行相同的计算。它不混合不同位置的信息这与注意力机制形成互补而是对每个位置已经丰富的表示进行更深层次的非线性变换增强模型的表达能力。3.2 多层堆叠从局部到全局的抽象之旅单个Encoder层完成了一次“信息聚合注意力深度加工FFN”的循环。多个这样的层堆叠起来就形成了深度的编码器。数据流动的层次化第1层主要关注基于词嵌入和位置编码的、相对表面的词汇间关系。例如“苹果”可能更多地与“吃”、“水果”等词建立联系。中间层开始捕捉更复杂的句法结构和语义角色。例如学习主谓宾关系、修饰关系等。高层接近输出编码的信息越来越抽象和任务相关。对于翻译任务高层表示可能更偏向于一种“语义中间语言”对于分类任务[CLS]token的表示可能汇聚了整个句子的高级语义。每一层都接收前一层的输出作为输入并在此基础上进行新一轮的信息整合与提炼。通过这种层层递进的方式模型能够构建出从局部到全局、从具体到抽象的深度表示。4. Decoder的数据流动自回归生成与上下文注入Decoder负责根据Encoder的编码结果自回归地一个一个token地生成目标序列。它的数据流比Encoder更复杂因为它需要处理两种不同的注意力机制并严格遵循生成时的因果约束。4.1 单层Decoder的三段式数据流一个Decoder层包含三个子层数据流顺序如下输入上一时刻的输出/目标序列嵌入 -- 子层1: 掩码多头自注意力 (Masked Multi-Head Self-Attention) -- Add Norm -- 子层2: 编码器-解码器注意力 (Encoder-Decoder Attention) -- Add Norm -- 子层3: 前馈网络 (Feed-Forward Network) -- Add Norm -- 输出4.1.1 掩码多头自注意力只能看见“过去”这是与Encoder自注意力最大的不同。在训练时我们通常将整个目标序列输入Decoder教师强制但为了模拟推理时只能看到已生成词的情况必须使用注意力掩码。掩码操作在计算注意力分数QK^T之后Softmax之前将未来位置j i对于当前位置i的分数设置为一个极大的负数如-1e9。数据流影响经过Softmax后未来位置的权重几乎为0。这意味着在生成第i个token时它的表示只依赖于它自身以及它之前的所有token1到i-1。这保证了模型在训练和推理时行为的一致性是自回归生成的核心。4.1.2 编码器-解码器注意力连接源与目标的桥梁这是Decoder获取源序列输入信息的唯一通道。它的Query来自Decoder上一子层的输出而Key和Value则来自Encoder的最终输出。数据流动Q Decoder_Output * W_QK Encoder_Output * W_KV Encoder_Output * W_V物理意义Decoder的每个位置目标token都可以“询问”QueryEncoder的所有位置源token找到与当前生成最相关的源端信息通过注意力权重并将这些信息Value聚合起来注入到当前的目标表示中。在翻译任务中这实现了经典的“对齐”功能。4.1.3 前馈网络与Encoder中的FFN完全相同对每个位置进行独立的非线性变换。4.2 训练与推理时数据流的差异理解这一点至关重要它解释了为什么Transformer能用于生成任务。训练时Teacher Forcing输入完整的目标序列右移一位即加上起始符sos。Decoder输入这个右移后的序列的嵌入。Decoder输出模型预测的整个序列每个位置预测下一个token。掩码确保预测位置i时只看到目标序列中i之前的部分。损失计算将Decoder的整个输出序列与真实的目标序列未右移进行交叉熵损失计算。这是一个并行过程模型一次性看到整个目标序列尽管被掩码因此训练效率极高。推理时自回归生成起始输入起始符sos给Decoder。循环Decoder基于当前已生成的所有token运行一次前向传播得到下一个token的预测分布。从分布中采样或取argmax得到下一个token。将这个新token拼接到已生成序列后作为新的输入重复步骤1。关键点这是一个串行过程。生成第N个token需要运行N次Decoder的前向传播。为了加速通常会使用KV缓存Key-Value Cache技术缓存之前所有步骤中计算好的K和V避免重复计算。5. 架构变体主流模型如何裁剪数据流图原始的Transformer是一个完整的Encoder-Decoder架构。但如今最成功的模型大多采用了其简化变体。从数据流动的角度看它们本质上是裁剪了完整的数据流图。5.1 Encoder-Only 架构以BERT为代表数据流裁剪完全移除Decoder部分。数据流动输入序列经过多层Encoder堆叠每个token的输出都融合了双向的上下文信息。任务适配这种架构天然适合需要理解整个输入序列的任务如掩码语言模型MLM随机掩码一些输入token让模型根据所有上下文来预测它。这要求模型具备双向理解能力。句子分类在序列前添加特殊的[CLS]token用其最终层的输出作为整个序列的表示进行分类。序列标注如命名实体识别直接用每个token的最终输出进行分类。核心特点双向上下文编码。每个位置在计算表示时都能“看到”序列中所有其他位置。5.2 Decoder-Only 架构以GPT系列为代表数据流裁剪完全移除Encoder部分以及Decoder中的“编码器-解码器注意力”子层。数据流动输入序列即待生成的文本前缀直接进入被裁剪后的Decoder层。每一层只包含掩码多头自注意力确保因果性Add Norm前馈网络Add Norm任务适配纯自回归语言建模。给定一个文本前缀预测下一个token的概率分布。通过堆叠极深的Decoder层如GPT-3有96层模型在庞大的无监督文本上训练学会了惊人的语言生成和上下文理解能力。核心特点单向自回归生成。这是当前大语言模型LLM的绝对主流架构。它的成功证明了在足够大的数据和模型规模下仅凭单向的注意力掩码和深层的非线性变换就能学习到丰富的世界知识。5.3 对比与选择架构核心数据流上下文方向典型任务代表模型Encoder-Decoder完整双向编码 条件自回归解码编码器双向解码器单向序列到序列任务翻译、摘要、对话T5, BART, 原始TransformerEncoder-Only仅双向编码完全双向理解类任务分类、标注、MLMBERT, RoBERTaDecoder-Only仅因果自回归解码严格单向生成类任务文本生成、代码生成GPT系列, LLaMA, ChatGLM从数据流视角看选择哪种架构取决于你的任务需要模型具备哪种信息获取能力是需要理解整个输入Encoder还是需要生成序列Decoder还是两者都需要完整架构。6. 实战中的关键细节与“反直觉”认知理解了宏观数据流再看一些实现细节和常见误区会有豁然开朗的感觉。6.1 注意力计算中的“批次矩阵乘法”视角我们经常看到注意力公式是向量形式。但在实际代码如PyTorch中一切都是通过批次矩阵乘法torch.bmm或torch.matmul高效完成的。对于一个注意力头假设batch_size2, seq_len5, d_k64Q形状[2, 5, 64]K形状[2, 64, 5](需要转置最后两维)Scores torch.matmul(Q, K.transpose(-1, -2))得到形状[2, 5, 5]。这个操作一次性计算了批次内所有样本、所有查询-键对之间的点积。后续的缩放、掩码、Softmax、与V的乘法都是基于这个[batch, seq_len, seq_len]的矩阵进行操作。这种“向量化”计算是Transformer能够高效并行处理整个序列的关键也是其相比RNN的巨大速度优势所在。6.2 层归一化与残差连接的顺序之争如前所述“Pre-LN” (LayerNorm - Sublayer - Add) 和 “Post-LN” (Sublayer - Add - LayerNorm) 都能工作但特性不同。Post-LN原始论文梯度需要流经整个子层的非线性变换后才被归一化在极深网络中如12层以上可能导致梯度不稳定需要精细的初始化如Xavier和学习率预热。Pre-LN现在更常用先将输入归一化再进入子层。这使得每一层的输入分布更稳定大大降低了训练难度允许训练更深、更宽的模型通常不需要学习率预热。大多数现代大模型如GPT、LLaMA都采用Pre-LN。数据流影响Pre-LN改变了梯度流动的路径使得主分支残差路径在进入非线性子层前就被“平滑”了优化起来更顺畅。6.3 为什么前馈网络需要那么大维度FFN的中间层维度如4*d_model通常远大于模型维度。这可以被看作是一个“瓶颈”结构d_model - 4*d_model - d_model。作用一增加非线性容量。更大的中间维度意味着更强大的非线性变换能力可以让模型学习更复杂的特征交互。有研究认为FFN是Transformer中存储事实知识的主要地方。作用二与注意力形成功能互补。注意力是“交互式”的混合了所有位置的信息FFN是“位置独立”的专门深化每个位置自身的表示。两者结合实现了信息交换与深度加工的完美配合。从数据流角度看向量经过注意力层后携带了全局信息但可能“稀释”了自身特性FFN则像一个精加工车间对每个携带全局信息的向量进行独立的、高维度的非线性锻造使其表达力更强。追踪Transformer中的数据流动就像观察一条信息的生命历程。它从离散的符号出发被赋予位置然后进入一个由无数条“注意力-残差-归一化-前馈”环路构成的深井。在Encoder的井里它与所有同伴自由交谈融合成一种集体的智慧。在Decoder的井里它一边回顾自己已走过的路掩码注意力一边聆听来自Encoder井底的箴言交叉注意力最终孕育出下一个新的符号。而像BERT和GPT这样的巨人则选择只挖掘其中一口井将其深度和广度拓展到极致同样改变了世界。理解这个流动过程不仅能让你更透彻地读懂论文和代码更能让你在设计和调试自己的模型时拥有清晰的直觉和方向。下次当你调整一个超参数或修复一个bug时不妨在脑海中想象一下数据流经那里时发生了什么改变。