Skip to content

Transformer:现代 AI 的地基 ​

这一篇是整条路线的枢纽。 懂了它,L4 的大模型原理、L5 的 RAG 与上下文工程都会变得自然。

一句话 ​

Transformer = 自注意力 + 前馈网络 + 残差 + LayerNorm,层层堆叠。

原文标题 Attention Is All You Need(2017)—— 它把 RNN 从序列建模里彻底移除了。

整体结构 ​

输入 token ids
   ↓ Embedding + 位置编码
┌──────────────────────────────┐
│  × N 层                       │
│   ├─ LayerNorm                │
│   ├─ 多头自注意力              │
│   ├─ 残差 +                  │
│   ├─ LayerNorm                │
│   ├─ 前馈网络 FFN             │
│   └─ 残差 +                  │
└──────────────────────────────┘
   ↓ LayerNorm
   ↓ Linear → vocab 维度
   ↓ Softmax → 下一个 token 的概率

其中「× N 层」里,每一层的内部就是这条链路:

1
LayerNorm先归一化,再进子层
2
多头自注意力token 之间交换信息
3
残差相加x + Attn(LN(x))
4
LayerNorm再归一化一次
5
FFN逐 token 独立变换
6
残差相加回到主干,进下一层
编码器(BERT)解码器(GPT)
双向注意力(能看左右)因果注意力(只能看左边)
适合理解类任务适合生成类任务

今天的 LLM 几乎都是 decoder-only。

一、位置编码:没有它,Transformer 是「词袋」 ​

自注意力本身不知道顺序:打乱输入,输出的集合不变。必须额外注入位置信息。

方案说明代表
正弦位置编码固定公式,无参数原始 Transformer
可学习位置嵌入每个位置一个向量BERT、GPT-2
RoPE(旋转位置编码)把位置信息旋转进 Q/KLLaMA、Qwen、绝大多数现代 LLM
ALiBi用距离惩罚偏置部分长文本模型
python
import math, torch

def sinusoidal_pe(max_len, d_model):
    pe = torch.zeros(max_len, d_model)
    pos = torch.arange(max_len).unsqueeze(1).float()
    div = torch.exp(torch.arange(0, d_model, 2).float() * -(math.log(10000.0) / d_model))
    pe[:, 0::2] = torch.sin(pos * div)
    pe[:, 1::2] = torch.cos(pos * div)
    return pe        # (max_len, d_model)

为什么 RoPE 重要

它让「相对位置」自然编码进点积,且便于外推到更长上下文(配合插值方法)。你在 L4 会看到「上下文扩展」的技术都建立在它之上。

二、前馈网络 FFN:参数最多的部分 ​

python
class FFN(nn.Module):
    def __init__(self, d_model, d_ff=None, dropout=0.1):
        super().__init__()
        d_ff = d_ff or d_model * 4
        self.net = nn.Sequential(
            nn.Linear(d_model, d_ff), nn.GELU(),
            nn.Dropout(dropout), nn.Linear(d_ff, d_model))
    def forward(self, x): return self.net(x)

注意:一个 Transformer 层里,FFN 的参数通常是注意力的 2 倍(4d² vs 4d²,但 FFN 中间层 4d 使之为 8d²)。

在 LLaMA 类模型里,FFN 用的是 SwiGLU(三个矩阵 + 门控),参数量更多: FFN(x) = (SiLU(xW₁) ⊙ xW₃)W₂,中间维度约为 8/3 d。

三、残差与 LayerNorm:能训深的原因 ​

python
class Block(nn.Module):
    def __init__(self, d_model, n_heads, dropout=0.1):
        super().__init__()
        self.norm1 = nn.LayerNorm(d_model)
        self.attn = MultiHeadAttention(d_model, n_heads)   # 见序列一章
        self.norm2 = nn.LayerNorm(d_model)
        self.ffn = FFN(d_model)
        self.drop = nn.Dropout(dropout)

    def forward(self, x, mask=None):
        # Pre-LN:先归一化再进子层(现代标准,训练更稳)
        x = x + self.drop(self.attn(self.norm1(x), self.norm1(x), self.norm1(x), mask))
        x = x + self.drop(self.ffn(self.norm2(x)))
        return x
设计Post-LN(原始)Pre-LN(现代)
顺序LN(x + F(x))x + F(LN(x))
训练稳定性需精心 warmup稳定得多
采用者BERTGPT-2 之后全部

LayerNorm vs BatchNorm:LN 在特征维归一化,与 batch 大小无关,序列长度不一也不受影响 —— 这就是 NLP 不用 BN 的原因。

四、把 Transformer 拼起来 ​

python
class MiniGPT(nn.Module):
    def __init__(self, vocab, d_model=256, n_heads=8, n_layers=4, max_len=512):
        super().__init__()
        self.tok_emb = nn.Embedding(vocab, d_model)
        self.pos_emb = nn.Embedding(max_len, d_model)
        self.blocks = nn.ModuleList([Block(d_model, n_heads) for _ in range(n_layers)])
        self.norm = nn.LayerNorm(d_model)
        self.head = nn.Linear(d_model, vocab, bias=False)

    def forward(self, ids):
        B, T = ids.shape
        pos = torch.arange(T, device=ids.device)
        x = self.tok_emb(ids) + self.pos_emb(pos)
        mask = torch.tril(torch.ones(T, T, device=ids.device)).bool()
        for blk in self.blocks:
            x = blk(x, mask)
        return self.head(self.norm(x))       # (B, T, vocab) logits

训练目标极其简单:给定前 t 个 token,预测第 t+1 个。

python
logits = model(ids[:, :-1])          # 输入去掉最后一个
loss = F.cross_entropy(
    logits.reshape(-1, vocab),
    ids[:, 1:].reshape(-1),          # 标签是右移一位
    ignore_index=pad_id)

GPT 的全部魔法就在这四行。 规模上去了,能力就涌现了 —— 这就是 L4。

五、复杂度与为什么需要优化 ​

操作复杂度说明
自注意力$O(T^2 d)$序列长度平方,长文本的瓶颈
FFN$O(T d^2)$与长度线性
显存(注意力矩阵)$O(T^2 \times \text{heads})$长上下文的主要显存来源

对应的优化(L4 展开):

问题技术
注意力太慢/太占显存FlashAttention(分块计算,不落盘完整矩阵)
超长序列稀疏/滑窗注意力、线性注意力、Mamba
推理重复计算KV Cache
部署吞吐PagedAttention / vLLM / 连续批处理

六、常见变体对照 ​

模型族结构训练目标擅长
BERTEncoder-only掩码语言模型(MLM)分类、抽取、检索(embedding)
T5Encoder-DecoderSpan 去噪翻译、摘要
GPT / LLaMA / QwenDecoder-only下一 token 预测生成、通用对话、Agent
ViTEncoder(图像切 patch)分类 / 对比视觉
CLIP双塔对比图文对比跨模态检索

为什么 decoder-only 赢了

  1. 训练目标统一(就是预测下一个词),任何文本都能用
  2. 推理时天然支持「输入即上下文」,无需改结构
  3. 规模化时 scaling law 表现最好

七、动手验证(强烈建议做) ​

  1. 实现上面的 MiniGPT,在一个小语料(如莎士比亚/中文小说)上训练
  2. 观察 loss 从 ~4.2(随机)降到 ~2.0 左右
  3. 用温度参数采样生成,感受 temperature 与 top_p 的影响(见 Prompt 工程)
  4. 可视化第 1 层的注意力权重,看它学到了什么

做完这一步,你对大模型的理解会超过 80% 只会调 API 的人。

通过标准 ​

下一步 ​

→ PyTorch 工程习惯

AI 学习路线 · 从入门到专家