共计 1918 个字符,预计需要花费 5 分钟才能阅读完成。
背景:LLM 技术演进与 Scaling Law
大语言模型(LLM)的技术演进可以追溯到 2017 年 Transformer 架构的提出。Andrej 在演讲中特别强调了 Scaling Law 的重要性——模型性能随着参数规模、数据量和计算资源的增加呈现幂律增长。关键公式为:

$$L(N,D) = \left(\frac{N_c}{N}\right)^{\alpha_N} + \left(\frac{D_c}{D}\right)^{\alpha_D} + L_\infty$$
其中 $N$ 是参数量,$D$ 是训练数据量,$\alpha$ 为缩放指数。当模型规模突破临界点(如 GPT- 3 的 175B 参数)时,会出现涌现能力(Emergent Ability),即模型突然获得小规模模型不具备的新能力。
核心原理:Self-Attention 机制详解
自注意力机制的计算过程可分为三步:
- 线性投影:将输入 $X \in \mathbb{R}^{n\times d_{model}}$ 转换为 Q /K/ V 矩阵
$$Q = XW_Q, \quad K = XW_K, \quad V = XW_V$$
(图示:输入序列→Q/K/ V 投影过程)
- 注意力打分:计算缩放点积注意力
$$\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
- 多头融合:合并 $h$ 个注意力头的输出
$$\text{MultiHead} = \text{Concat}(head_1,…,head_h)W_O$$
代码实现:PyTorch 版 Transformer Block
# model.py
import torch
import torch.nn as nn
class TransformerBlock(nn.Module):
def __init__(self, d_model=512, n_heads=8):
super().__init__()
self.attention = nn.MultiheadAttention(d_model, n_heads)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.ffn = nn.Sequential(nn.Linear(d_model, 4*d_model),
nn.GELU(),
nn.Linear(4*d_model, d_model)
)
def forward(self, x, mask=None):
# x shape: [seq_len, batch, d_model]
attn_out, _ = self.attention(x, x, x, attn_mask=mask)
x = x + attn_out # 残差连接
x = self.norm1(x)
ffn_out = self.ffn(x)
x = x + ffn_out # 残差连接
return self.norm2(x)
关键实现细节:
– 使用 nn.MultiheadAttention 内置的 mask 机制支持因果注意力
– 采用 Pre-LN 结构(LayerNorm 在残差连接前)提升训练稳定性
– FFN 层使用 GELU 激活函数和 4 倍隐藏层扩展
生产实践关键技巧
1. 参数高效微调对比
| 方法 | 可训练参数量 | 显存占用 | 适用场景 |
|---|---|---|---|
| Full Fine-tuning | 100% | 极高 | 领域适配 |
| LoRA | 0.1%-1% | 低 | 轻量级任务适配 |
| Prefix Tuning | 0.5%-2% | 中 | 生成任务 |
2. KV Cache 加速推理
推理时通过缓存先前计算的 $K,V$ 矩阵,将自注意力复杂度从 $O(n^2)$ 降至 $O(n)$。显存占用公式:
$$\text{Mem}_{KV} = 2 \times b \times s \times h \times d_h \times \text{bytes}$$
其中 $b$ 是 batch size,$s$ 是序列长度,$h$ 是注意力头数,$d_h$ 是每个头的维度。
避坑指南
- Tokenizer 版本陷阱:不同版本的 tokenizer 可能产生不同的分词结果,导致生产环境与训练时不一致。解决方案:
- 固化 tokenizer 版本
-
保存 vocab.json 等配置文件
-
BF16 精度丢失:部分 GPU 架构(如 Ampere)使用 bfloat16 时可能出现梯度异常。解决方案:
- 混合精度训练时保留 FP32 主副本
-
使用
torch.autocast上下文管理器 -
序列长度超限:超过预训练最大长度(如 2048)时性能骤降。解决方案:
- 采用 NTK-aware 位置编码扩展
- 使用 ALiBi 等相对位置编码
开放问题讨论
- 如何平衡模型规模与推理成本的关系?是否存在最优的 ” 性价比 ” 临界点?
- 当涌现能力出现时,模型内部表征发生了哪些本质变化?有哪些可观测的指标?
(全文完)
