Transformer 模型自 2017 年问世以来,彻底改变了自然语言处理(NLP)的版图。它不但推动了机器翻译的质变,也奠定了 ChatGPT、Bard 等大模型的基石。而其中,解码器(Decoder)就是 Transformer 中最具有“生成魔力”的部分,专门用于从模型的内部语义表示中一步步产生输出文本。

如果说 编码器(Encoder)是 Transformer 的大脑,用来理解输入,那么 解码器(Decoder)就像嘴巴,用来表达并生成符合人类语言习惯的输出。

今天,我们就带大家系统地理解解码器的设计原理、结构拆解、代码实现以及在实际任务中的应用。

一、解码器的总体结构

在 Transformer 的原始结构中,解码器由 多层堆叠的解码器层(Decoder Layer) 组成。每一层解码器包含 3 大模块:

  1. Masked Multi-Head Self-Attention
  2. Encoder-Decoder Attention(交叉注意力)
  3. 前馈全连接网络(FFN)

并且每一块都会带有子层连接结构(残差 + LayerNorm)。整体的流程看起来就像:

x
│
├──→ Masked Multi-Head Attention
│       + Add & Norm
├──→ Encoder-Decoder Attention
│       + Add & Norm
├──→ Position-wise FFN
│       + Add & Norm
↓
输出

从输入到输出,它会逐步完成“生成+对齐”的功能。

二、解码器的关键:Masked Multi-Head Attention

我们知道在编码器中,Multi-Head Attention 允许每一个 token 看见其他所有 token,而在 解码器里情况不一样。因为解码器要做的是 一步一步 预测下一个 token。不能“作弊”看未来的词,所以需要 Masked Attention。

其原理就是在计算 self-attention 的 softmax 权重时,对未来 token 的部分打上一个非常大的负无穷遮罩,防止信息泄露。这样模型就只能基于目前已经生成的 token 来推断下一个 token。

三、Encoder-Decoder Attention(交叉注意力)

这是解码器层与编码器层的最大区别。
当解码器正在生成句子时,需要同时参考输入序列的信息(比如翻译场景中的原文)。

因此,第二个注意力模块就是:

Q  ← 来自解码器
K,V ← 来自编码器

通过 Q 和 K 计算关联性,就能从 Encoder 的输出中找到与当前生成位置最匹配的上下文信息。

四、前馈全连接网络(FFN)

和 Encoder 中一样,每个 token 位置都会通过同一个 MLP:

FFN(x) = max(0, xW1 + b1)W2 + b2

来做非线性映射,增加解码器的表达能力。

五、子层连接(残差连接 + 规范化)

x = LayerNorm(x + Sublayer(x)

它能:

  • 稳定训练
  • 避免退化
  • 让梯度传递更流畅

六、PyTorch 解码器层实现

下面给出一个标准解码器层的可运行 PyTorch 代码,帮助大家一目了然:

import torch
import torch.nn as nn
 
class DecoderLayer(nn.Module):
    def __init__(self, d_model=512, heads=8, d_ff=2048, dropout=0.1):
        super().__init__()
        self.self_attn = MultiHeadAttention(d_model, heads)
        self.cross_attn = MultiHeadAttention(d_model, heads)
        self.ffn = PositionwiseFeedForward(d_model, d_ff, dropout)
 
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.norm3 = nn.LayerNorm(d_model)
 
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)
        self.dropout3 = nn.Dropout(dropout)
 
    def forward(self, x, encoder_output, src_mask=None, tgt_mask=None):
        # masked self-attention
        _x = self.self_attn(x, x, x, tgt_mask)
        x = self.norm1(x + self.dropout1(_x))
 
        # encoder-decoder cross-attention
        _x = self.cross_attn(x, encoder_output, encoder_output, src_mask)
        x = self.norm2(x + self.dropout2(_x))
 
        # feed forward
        _x = self.ffn(x)
        x = self.norm3(x + self.dropout3(_x))
        return x

这里的 MultiHeadAttention 与 PositionwiseFeedForward,可以沿用前面 Encoder 中的实现。

七、解码器堆叠:Transformer Decoder

通常我们把多个解码器层堆叠起来形成完整的解码器:

class TransformerDecoder(nn.Module):
    def __init__(self, vocab_size, d_model=512, N=6, heads=8, d_ff=2048, dropout=0.1):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.pos_encoding = PositionalEncoding(d_model, dropout)
        self.layers = nn.ModuleList([
            DecoderLayer(d_model, heads, d_ff, dropout) for _ in range(N)
        ])
        self.norm = nn.LayerNorm(d_model)
 
    def forward(self, tgt, encoder_output, src_mask=None, tgt_mask=None):
        x = self.embedding(tgt)
        x = self.pos_encoding(x)
        for layer in self.layers:
            x = layer(x, encoder_output, src_mask, tgt_mask)
        return self.norm(x)

八、解码器的训练与推理

  • 训练阶段:可以使用并行方式输入一整句话,让模型一次性预测每个位置的 token(teacher forcing)。
  • 推理阶段:必须“逐步”预测,每次输出一个 token,再把它喂回去。这样才能模拟真实的文本生成。
    举个例子:
<sos> → I
<sos> I → am
<sos> I am → a
<sos> I am a → student

这种 token-by-token 生成就是 ChatGPT 工作方式的灵感来源。

九、实际应用案例:英法翻译

比如你想实现一个英法翻译器:

  • 英文句子输入编码器
  • 法文起始符 输入解码器
  • 解码器利用编码器信息,依次输出法语单词
    下面给一个极简示例:
class SimpleTranslator(nn.Module):
    def __init__(self, src_vocab_size, tgt_vocab_size):
        super().__init__()
        self.encoder = TransformerEncoder(src_vocab_size)
        self.decoder = TransformerDecoder(tgt_vocab_size)
        self.out_proj = nn.Linear(512, tgt_vocab_size)
 
    def forward(self, src, tgt, src_mask=None, tgt_mask=None):
        memory = self.encoder(src, src_mask)
        dec_out = self.decoder(tgt, memory, src_mask, tgt_mask)
        return self.out_proj(dec_out)

只要把你的语料数据(英文->法文)传进去训练,这个模型就可以从头学会翻译。

十、常见改进

问题 改进方向
推理太慢 使用并行 beam search / flash decoding
长文本受限 引入稀疏注意力或滑动窗口
低资源下过拟合 使用共享词嵌入、权重共享
表达能力不足 增加解码器层数 / MoE 模块

十一、总结

模块 作用
Masked Attention 防止看到未来 token
Cross Attention 对齐编码器的信息
FFN 增强每个 token 表达能力
LayerNorm + 残差 稳定训练,防止梯度消失
堆叠结构 逐层提升生成能力

可以说,Transformer 的解码器层,就是大语言模型得以顺畅“说话”的秘密所在。
如果没有它,我们今天就不会有 ChatGPT、Gemini 甚至是多模态 Sora 的流畅自然输出。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐