Transformer 为什么要堆叠多层编码器和解码器:从一层计算到深层表示
围绕编码器、解码器层结构,解释单层 Transformer 的职责、多层堆叠带来的表示变化,以及残差和归一化为什么贯穿每一层。
相关工具
先把一层 Transformer 看完整
Transformer 的编码器层不是一个单独的注意力模块,而是一段有固定顺序的计算:多头自注意力、残差连接与归一化、前馈网络、再次残差连接与归一化。输入和输出通常保持相同的模型维度,方便这一层继续接到下一层。
资料 对编码器的描述也是沿着这条路径展开的:每个编码器接收一组向量,先经过 Self-Attention,再经过前馈网络,输出交给下一个编码器。单层的工作可以概括成两件事:先让位置之间交换信息,再让每个位置独立加工自己的特征。
解码器层比编码器多一个 Encoder-Decoder Attention。它先处理已经生成的目标前缀,再查询编码器输出的源序列表示,最后经过前馈网络。多层堆叠之前,先把这两个基本单元看清楚,后面的深度才有意义。

一层编码器依次经过多头自注意力、Add & Norm、前馈网络和第二次 Add & Norm,并保留两条残差路径。
为什么一层还不够
一层自注意力可以让每个位置读取其他位置的信息,但它得到的仍然是一次上下文混合后的表示。某个词和另一个词建立了联系,不等于模型已经完成了指代、句法和更高层语义的判断。
前馈网络会对每个位置的表示做非线性变换,但它不直接负责位置之间的信息交换。注意力负责“看谁”,前馈网络负责“看完之后怎么加工”。一层把两种能力组合起来,却仍然只能进行一次这样的交替。
堆叠多层的意义,就是让表示反复经历“交互与加工”。较浅的层可能更多处理局部关系,中间层逐渐组合上下文,较深的层则有机会形成面向整个任务的抽象表示。实际模型不一定严格按这个顺序分工,但深度提供了多次重组信息的空间。
堆叠时形状为什么保持不变
如果输入序列表示是 [seq, d_model],经过一层编码器后通常仍然是 [seq, d_model]。注意力内部可以把 d_model 拆成多个头,前馈网络也可以暂时扩展到更大的中间维度,但模块出口会回到 d_model。
形状不变让第 1 层的输出可以直接作为第 2 层输入,第 2 层再接到第 3 层。堆叠的不是形状越来越大的张量,而是对同一组位置表示进行更深的变换。每层都在更新同一个序列位置集合,只是每个位置携带的信息越来越丰富。
这也解释了残差连接为什么重要。如果每个子层都改变最后一维,输入与输出就无法直接相加;让层边界保持 d_model,既便于连接,也便于在深层网络中保留原始信息。

每层都保持 [seq, d_model] 形状,表示的上下文范围和语义组合能力逐层增强。
浅层和深层表示有什么区别
输入嵌入主要提供词本身的表示和位置信息。经过第一层注意力后,每个位置开始包含其他位置的上下文;继续向上堆叠,模型可以把多个局部关系组合成更完整的句子结构。
例如一个代词需要结合前文判断指向谁,单层可能只能看到相关词的直接联系,多层则可以在不同位置之间反复传播和整理信息。对于机器翻译,编码器深层表示还需要为解码器提供足够清晰的源句语义。
不过,“越深越抽象”不是绝对规律。不同任务、训练数据和模型结构会让各层形成不同模式,不能仅凭层数断言某一层一定对应某种语言学现象。更稳妥的说法是:深度让模型拥有更多次上下文交互和非线性变换的机会。
残差连接如何帮助深层堆叠
如果每一层都完全替换输入,信息需要连续穿过很多个子层,早期表示可能逐渐被冲淡,梯度也要经过更长的路径。残差连接给每个子层旁边保留一条直接路径,让子层只需要学习在原表示上增加什么变化。
可以把注意力子层理解为对输入做一次上下文修正,前馈子层再做一次特征修正。它们的输出和原输入相加,意味着每层既能更新表示,也能保留已经存在的信息。层数增加后,这种“增量式更新”比每次从零构造表示更容易训练。
残差连接并不代表每层都应该只做很小的变化,而是给模型提供了一个更容易优化的基线。必要时,子层可以产生较大的调整;如果某一层暂时不需要复杂变化,也有一条路径让信息继续向后传递。
LayerNorm 为什么跟着每个子层出现
残差相加会把两路信息合并,数值尺度可能随层数变化。LayerNorm 对每个位置的特征进行归一化,让后续子层面对相对稳定的输入范围。它与缩放点积里的 sqrt(d_k) 不同:前者作用于特征表示,后者作用于注意力分数。
在不同实现中,LayerNorm 可能放在子层前面或子层与残差相加之后,形成 Pre-Norm 或 Post-Norm 结构。二者的具体训练性质有所区别,阅读模型时要看清归一化位于哪条路径。
无论采用哪种布局,核心目标都与深层堆叠有关:让每层的输入和梯度保持可控,避免层数增加后数值越来越难处理。LayerNorm 不是让模型自动理解语言的模块,它主要负责给深层计算提供稳定条件。
解码器为什么也要堆叠多层
解码器的每一层都要处理目标前缀和源序列信息。第一步是带因果掩码的自注意力,确保当前目标位置看不到未来;第二步是 Encoder-Decoder Attention,让目标位置查询编码器输出;第三步是前馈网络,对融合后的表示进行变换。
堆叠后,目标序列表示可以反复更新。较低层先整理已经生成的目标上下文,中间的交叉注意力把源句信息引入当前表示,更高层继续加工与输出词选择相关的特征。实际计算中每一层都可能同时使用这些信息,只是组合方式逐层变化。
编码器和解码器的层数可以相同,也可以不同,取决于模型设计。重要的不是机械地追求相同层数,而是让编码器产生的 memory 足以支持解码器的交叉注意力,让解码器有足够深度完成目标序列建模。

源序列经过 N 层编码器形成 memory,目标前缀经过 N 层解码器,并在每层通过交叉注意力读取 memory。
层数增加不等于效果一定更好
增加层数会带来更强的表示能力,但也会增加参数量、计算量和训练难度。数据量不足时,深层模型可能更容易记住训练样本;优化设置不合适时,训练速度和稳定性也会受到影响。
层数还会影响推理延迟。生成一个 token 时,解码器需要通过每一层完成一次前向计算,层数越多,单步成本越高。缓存 Key 和 Value 可以减少重复计算,却不能把多层计算完全省掉。
因此,层数是模型容量、泛化、速度和成本之间的平衡参数。不能只根据“更深”来判断架构好坏,需要结合任务难度、数据规模、验证集表现和实际响应要求一起评估。
如何读懂一张 Transformer 结构图
看到一组重复的 Encoder Layer 或 Decoder Layer 时,先找输入和输出的形状,再看每层内部是否包含注意力、前馈、残差和归一化。重复的方框表示参数可能独立,也可能采用某种共享设计,不能默认所有层使用同一组参数。
接着找信息流向。编码器层之间通常是串联,后一层接收前一层的完整序列表示;解码器层还会从编码器输出拉出一条交叉注意力连接。若图中出现 Mask,要判断它属于解码器自注意力,还是用于排除 Padding。
最后看最顶层输出。编码器堆叠的最终结果通常作为 memory,解码器堆叠的最终结果进入线性层和 Softmax,变成词表概率。这样就能把层数、数据流和最终任务联系起来,而不是只数有多少个方框。
把多层堆叠放回 Transformer 主线
Transformer 用同一种层级结构反复加工序列表示:注意力让位置之间交换信息,前馈网络在每个位置上做非线性变换,残差连接保留信息通路,LayerNorm 控制数值尺度。编码器把这组操作堆叠起来,解码器则在此基础上增加目标侧的因果约束和源目标交互。
一层解决的是一次信息交互和一次特征加工,多层提供的是连续的表示更新。层数并不会改变序列中有多少个位置,改变的是每个位置能够利用多少上下文、组合多少关系,以及最后用于任务的表示质量。
理解这一点后,Transformer 的“深度”就不再只是堆方框。它代表模型有多少次机会重新组织上下文,也代表训练、推理和参数成本会随之增加。架构设计真正要回答的问题,是需要多少次这样的表示更新,才能让任务得到稳定收益。
常见问题
编码器为什么可以重复堆叠?
因为每层通常保持 [seq, d_model] 的输入输出形状,上一层的序列表示可以直接作为下一层输入,同时残差连接和归一化帮助深层计算保持稳定。
层数越多,Transformer 一定越强吗?
不一定。更多层数带来更强的表示能力,也会增加过拟合风险、训练难度、参数量和推理成本,需要结合数据和任务验证。
解码器为什么比编码器多一个注意力子层?
解码器除了建模目标前缀,还需要通过 Encoder-Decoder Attention 读取编码器输出的源序列信息,因此每层多一个交叉注意力子层。