2. Transformer架构速览

聊蒸馏之前,咱们得先把 Transformer 这个底子摸透。说白了,不管你是做 BERT 还是 GPT,底层都是那几板斧:Attention、FFN、LayerNorm。我刚开始接触时也觉得这玩意儿玄乎,后来拆开一看,其实没那么复杂。

1. 核心三件套:Attention、FFN、LayerNorm

Transformer 的每个 Block 就干三件事:让信息互相看看(Attention)、自己想想(FFN)、最后归一化稳住训练(LayerNorm)。

1.1 Self-Attention:让每个词都“看见”其他词

Attention 的公式大家应该都见过:

Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) * V

Q、K、V 都是从输入向量通过线性变换得到的。点积算相似度,softmax 归一化成权重,最后加权求和。我习惯把这一步理解为“每个词都在问:谁跟我最相关?”

我的经验: 实际部署时,QK^T 这一步是计算瓶颈。序列长度一长,显存直接爆炸。我曾在 512 长度的序列上跑 BERT-base,单卡 16G 显存差点撑不住。

1.2 FFN:给每个位置“独立思考”的能力

Attention 做完后,每个位置拿到的是融合了全局信息的向量。但还不够,得再经过两层全连接“消化”一下:

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

中间隐层维度通常是 4 倍 d_model。比如 BERT-base 的 d_model=768,中间层就是 3072。参数量大头其实在这儿,不是 Attention。

1.3 LayerNorm:稳住训练节奏

LayerNorm 做的事情很简单:对每个样本的所有维度做归一化,再学两个缩放和平移参数。公式:

LayerNorm(x) = gamma * (x - mean) / sqrt(var + eps) + beta

嗯,这里要注意:LayerNorm 是在特征维度上做的,不是 batch 维度。跟 BatchNorm 不一样,Transformer 里清一色用 LayerNorm。

2. 从 BERT 到 GPT:架构差异在哪?

BERT 和 GPT 都是 Transformer,但设计哲学完全不同。我整理了一张对比表:

维度 BERT GPT
注意力模式 双向(Bidirectional) 单向(Causal / Autoregressive)
训练目标 MLM + NSP 语言模型(Next Token Prediction)
典型应用 分类、NER、QA 文本生成、对话
位置编码 绝对位置编码(Sinusoidal / Learned) 绝对位置编码(Learned)
参数量级 BERT-base: 110M GPT-2: 1.5B

说白了,BERT 像阅读理解——能看到上下文;GPT 像写作文——只能看前面。这个差异直接决定了蒸馏时的策略:BERT 蒸馏可以并行做,GPT 蒸馏得考虑自回归的时序依赖。

3. 参数量与计算量的关系

这个我得多说两句。很多同学只看参数量,觉得模型大就慢。其实计算量(FLOPs)才是推理延迟的关键。

3.1 参数量怎么算?

以 Transformer Block 为例:

  • Attention 部分: Q、K、V 各一个线性层,输出一个线性层。每个线性层参数 = d_model * d_model。所以 Attention 总参数量 ≈ 4 * d_model^2。
  • FFN 部分: 两个线性层,参数量 = d_model * d_ff + d_ff * d_model = 2 * d_model * d_ff。d_ff 通常是 4 * d_model,所以 ≈ 8 * d_model^2。
  • LayerNorm: 每个 LayerNorm 2 个参数(gamma、beta),可以忽略不计。

一个 Block 总参数量 ≈ 12 * d_model^2。BERT-base 有 12 层,d_model=768,算下来 ≈ 12 * 12 * 768^2 ≈ 85M,加上 Embedding 和偏置,差不多 110M。

3.2 计算量(FLOPs)怎么估?

计算量跟序列长度 L 强相关。Attention 的计算量是 O(L^2 * d_model),FFN 是 O(L * d_model * d_ff)。

我举个例子:BERT-base 在序列长度 512 时,单次前向传播的 FLOPs 大约:

  • Attention:12 层 * 12 头 * (512^2 * 64) ≈ 2.4G FLOPs
  • FFN:12 层 * (512 * 3072 * 768 * 2) ≈ 28.9G FLOPs
  • 总 FLOPs ≈ 31.3G
关键结论: FFN 的计算量远大于 Attention(约 12 倍)。所以蒸馏时,优先压缩 FFN 的维度往往收益最大。

4. 一张图看懂 Transformer 核心流程

下面这张 SVG 图展示了 Transformer Block 的内部结构,以及参数量和计算量的分布关系:

Transformer Block 核心结构 Transformer Block 核心结构 & 计算量分布 输入向量 (d_model) LayerNorm Multi-Head Attention 计算量: O(L²·d_model) Add + LayerNorm Feed-Forward Network 计算量: O(L·d_model·d_ff) Add + LayerNorm 参数量占比 Attention: ~4·d_model² FFN: ~8·d_model² LayerNorm: 可忽略 蒸馏关注点 FFN 计算量占比 ~90% 优先压缩 FFN 维度

5. 蒸馏视角下的关键洞察

了解了这些,咱们再回头看蒸馏,思路就清晰了:

  • Attention 层: 决定模型“看多远、看多准”。蒸馏时要注意保留注意力分布的结构,不能乱剪。
  • FFN 层: 参数量最大,计算量也最大。我建议优先从这里下手,比如减少中间隐层维度。
  • LayerNorm: 参数少,但影响训练稳定性。蒸馏时最好保留,或者用更简单的归一化替代。
我曾经踩过的坑: 有一次我直接砍掉了一半的 FFN 维度,结果模型精度掉了 5 个点。后来发现是没做知识蒸馏的 soft label 对齐,光剪参数不调损失函数,等于白干。