深度学习现代架构(Transformer / Diffusion / MoE)
先把结论放前面
Transformer、Diffusion、MoE 是当前 AI 系统的三大核心架构:
- Transformer(2017)是几乎所有 NLP 和多模态模型的基座,核心是 Self-Attention
- Diffusion Model(2020)是图片生成的主流范式,核心是逐步去噪
- MoE(2021+)是 scaling 大模型的核心技术,核心是稀疏激活
理解这三个架构的核心机制,能让你在设计系统和做技术选型时少走很多弯路。
Transformer:Attention is All You Need
Self-Attention 的计算过程
Transformer 的核心是 Self-Attention(自注意力)。对输入序列的每个 token,分别计算 Query、Key、Value 三个向量,然后做加权求和:
import torch
import torch.nn.functional as F
import math
def self_attention(Q, K, V, mask=None):
"""
Q, K, V: (batch, seq_len, d_k)
返回: (batch, seq_len, d_k)
"""
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attn_weights = F.softmax(scores, dim=-1)
return torch.matmul(attn_weights, V)
Multi-Head Attention(MHA)
为什么需要多个 Head:不同的 Head 关注不同的语义关系(主语、动词、位置邻近词、指代关系)。
class MultiHeadAttention(nn.Module):
def __init__(self, d_model=512, num_heads=8):
super().__init__()
self.num_heads = num_heads
self.d_k = d_model // num_heads
self.W_q = nn.Linear(d_model, d_model)
self.W_k = nn.Linear(d_model, d_model)
self.W_v = nn.Linear(d_model, d_model)
self.W_o = nn.Linear(d_model, d_model)
def forward(self, x):
B, T, C = x.shape
Q = self.W_q(x).view(B, T, self.num_heads, self.d_k).transpose(1, 2)
K = self.W_k(x).view(B, T, self.num_heads, self.d_k).transpose(1, 2)
V = self.W_v(x).view(B, T, self.num_heads, self.d_k).transpose(1, 2)
out = self_attention(Q, K, V)
out = out.transpose(1, 2).contiguous().view(B, T, C)
return self.W_o(out)
计算复杂度
Self-Attention 的核心问题是 O(n²) 复杂度:
- 每个 token 需要和所有 n 个 token 做交互
- 序列长度 n 增长时,显存和计算量爆炸
这是 Transformer 的核心瓶颈,也是所有 Transformer 变体试图解决的问题。
FlashAttention
FlashAttention 的核心思想:不用完整存储 N×N 的 Attention 矩阵,一边计算一边丢弃中间结果。
标准 Attention 需要存储完整的 Attention Matrix(S = QKᵀ),显存 O(n²)。FlashAttention 用分块计算(Tile),每次只处理一个 Block,显存降到 O(n)。
效果:64K 序列的 Attention,显存从 O(n²) 崩溃降到可承受范围。
KV Cache
在自回归生成时,每个新 token 都需要重新计算和前面所有 token 的 Attention。KV Cache 把已经计算过的 Key-Value Tensor 缓存起来,新 token 只需要和缓存拼接,不需要重新计算。
无 Cache:每生成 1 个 token,需要 O(n²) 计算
有 Cache:每生成 1 个 token,只需要 O(n) 追加计算
代价:显存占用和上下文长度成正比,n 个 token 需要 O(n) 显存存 KV。
Multi-Query Attention(MQA)vs Grouped-Query Attention(GQA)
MHA:每个 Head 有独立的 QKV,显存消耗最大。
MQA:所有 Head 共用一组 K 和 V,Q 各自独立。显存大幅节省(约 1/num_heads),推理速度提升,但效果可能略下降。
GQA:MHA 和 MQA 的中间方案。每个 Head Group 共用一组 KV。效果和 MHA 接近,速度和 MQA 接近。Llama 2/3 用的是 GQA。
位置编码(Positional Encoding)
Attention 本身不感知位置(Permutation Invariant),需要额外注入位置信息。
Sinusoidal PE(原始论文):用不同频率的正弦函数编码位置。
RoPE(Rotary Position Embedding,Llama 采用):把位置编码融进 Q 和 K 的旋转里,不需要加在 Embedding 上。
# RoPE 核心:旋转 Q 和 K
def apply_rotary(q, k, position_ids):
# 对 q 和 k 的每对相邻维度做旋转
for i in range(0, q.size(-1), 2):
angle = position_ids / 10000 ** (2 * i / q.size(-1))
q[..., i:i+2] = rotate(q[..., i:i+2], angle)
k[..., i:i+2] = rotate(k[..., i:i+2], angle)
return q, k
ALiBi(Attention with Linear Biases):不给 Embedding 加位置,直接在 Attention Score 上加线性偏差。
Diffusion Model
核心思想
Diffusion Model 的训练和采样是两个互逆过程:
Forward Process(加噪):逐步向图片加高斯噪声,最终变成纯噪声。
x₀(真实图片)→ x₁ → x₂ → ... → xT(纯噪声)
Reverse Process(去噪):训练一个模型学会逐步从噪声恢复图片。
xT(纯噪声)→ xT-1 → ... → x₁ → x₀(生成图片)
DDPM(Denoising Diffusion Probabilistic Models)
DDPM 的训练目标是让模型预测每一步加的噪声:
# DDPM 训练
for t in range(1, T+1): # T 通常=1000
noise = torch.randn_like(x₀)
x_t = sqrt(ᾱ_t) * x₀ + sqrt(1 - ᾱ_t) * noise # 加噪
loss = MSE(model(x_t, t), noise) # 预测噪声
采样(生成):
# DDPM 采样
x_T = torch.randn_like(x₀)
for t in reversed(range(1, T+1)):
z = torch.randn_like(x₀) if t > 1 else 0
x_{t-1} = (1/sqrt(ᾱ_t)) * (x_t - (1-ᾱ_t)/sqrt(1-ᾱ_t) * model(x_t, t)) + σ_t * z
DDPM 的问题:需要 T 步迭代才能生成一张图,太慢。
DDIM(Denoising Diffusion Implicit Models)
DDIM 把生成过程从 T 步压缩到 20-50 步(采样加速 10-50 倍),同时保持图片质量。
核心:不再严格遵循马尔可夫链,用更长的步长跳跃式去噪。
Stable Diffusion(Latent Diffusion)
Stable Diffusion 的关键创新是不在像素空间而在 Latent 空间生成:
像素空间(512×512×3)→ Encoder → Latent 空间(64×64×4)
↓ 生成
Latent 空间(64×64×4)→ Decoder → 像素空间(512×512×3)
Latent 空间维度是像素空间的 1/64,大幅降低计算量,让消费级 GPU 生成高分辨率图片成为可能。
Classifier-Free Guidance(CFG)
CFG 是控制 Diffusion 模型输出的标准方法,不需要单独训练一个 Classifier。
# 有条件和无条件预测的加权
# guidance_scale 控制条件强度
predicted_noise = (1 + guidance_scale) * conditional_noise \
- guidance_scale * unconditional_noise
- CFG Scale = 1:无分类器引导,和正常生成一样
- CFG Scale = 7-12(常用):强条件引导,图片更符合 prompt,多样性降低
- CFG Scale 过高:图片过饱和、伪影
MoE(Mixture of Experts)
核心思想
Dense Transformer(GPT、LLaMA)是每个 token 都激活所有参数。MoE 的核心是稀疏激活:每个 token 只激活一小部分专家(Expert),其余专家不参与计算。
FFN 层替换为 MoE Layer:
MoE Layer = N 个 Expert(每个是独立的 FFN)
+ Router(决定每个 token 用哪些 Expert)
对于每个 token x:
Router(x) → Top-K experts
output = Σ (gate_i(x) × Expert_i(x))
为什么 MoE 能 scale
假设有 8 个 Expert,每次只激活 2 个:
- 参数量:8× 的 FFN 参数量
- 计算量:2× 的 FFN 计算量(和其他 Dense 模型一样)
结果:模型参数量大幅增加,但计算量不变——这是 scaling 的关键技巧。
Expert Load Balancing
Router 可能会"偷懒":总是把 token 发给少数几个 Expert(通常是 Expert 0),导致负载不均。
解决方案:Auxiliary Load Balancing Loss:
load_loss = α * N * Σ (fraction_i)²
# 其中 fraction_i = Router 对 Expert i 的 token 比例
# 理想情况:每个 Expert 得到 1/N 的 token,loss = α
# 偷懒情况:少数 Expert 收到大量 token,loss 显著增大
主流 MoE 模型
| 模型 | 参数量 | 激活参数 | Experts | 激活数 |
|---|---|---|---|---|
| Switch Transformer | 1.6T | 6B | 2048 | 1 |
| GLaM | 1.2T | 97B | 64 | 2 |
| Mixtral 8×7B | 46.7B | 12.9B | 8 | 2 |
| DBRX | 132B | 36B | 16 | 4 |
如果放到面试里怎么讲
"Transformer 的 O(n²) 复杂度怎么解决?"
有几个方向:FlashAttention 用分块计算避免存储完整 Attention 矩阵;MQA/GQA 减少 KV 头的数量;稀疏 Attention 只算部分 token 对。另外 RoPE/ALiBi 在位置编码上做优化,减少了绝对位置编码的计算开销。
"Diffusion Model 为什么需要多步生成,直接一步生成不行吗?"
直接预测最终图片太难了。多步去噪让模型在每一步只做小幅改进,逐步从噪声恢复图片,每一步的目标都比较简单。DDIM 证明了可以用更长的步长,跳过中间步骤,把生成步数压缩 10-50 倍而不明显损失质量。
最后记几个点
- Transformer 的核心是 Self-Attention,O(n²) 复杂度是其主要瓶颈
- FlashAttention 用分块计算降低显存,KV Cache 在推理时避免重复计算
- MQA/GQA 减少 KV 头数,RoPE 把位置编码融进旋转,是推理优化的关键
- Diffusion Model = Forward 加噪 + Reverse 去噪,DDPM 训练简单但采样慢
- Stable Diffusion 在 Latent 空间生成,CFG 控制条件强度
- MoE 用稀疏激活换参数量 scaling,每个 token 只激活 top-k experts
- MoE 的主要工程挑战是 Expert 负载均衡和通信开销
跨库关联
本文件的 Transformer/MoE 部分是概览级别,详细内容在 大模型知识库 中: