大模型基础:预训练、提示、微调与强化学习
一、Pretraining 和 Compute(预训练与算力)
1. Compute(计算量)是什么?
简单理解:训练一个大模型需要多少"计算工作量"。
公式:$C \approx 6ND$
- N:模型有多少参数(比如 70 亿个参数)
- D:喂给模型多少个词(token)来训练(比如 2 万亿个词)
- C:总计算量(用 FLOPs 衡量,就是"浮点运算次数")
举例:
- Llama 2(7B)模型:
- 70亿参数 × 2万亿tokens × 6 = $8.4 \times 10^{22}$ FLOPs
- 这个数字很大,需要很多 GPU 跑很多天
关键点:我们可以通过两种方式增加算力:
- 增加参数量 N(把模型做大)
- 增加训练数据量 D(喂更多文本)
2. Scaling Laws(规模定律)—— 预测模型性能的"公式"
核心发现:模型的性能(loss 越小越好)和算力之间有可预测的关系。
怎么用?
场景 1:预测大模型性能
- 我不想直接训练一个 700 亿参数的模型(太贵)
- 我先训练一堆小模型(10亿、30亿、70亿参数)
- 把每个小模型的"算力"和"loss"画成图
- 用线性回归拟合,得到公式:$\text{loss} = a \times \text{compute}^{-b}$
- 用这个公式预测:如果我训练 700 亿参数模型,loss 会是多少
场景 2:选最优配置(Chinchilla 论文的贡献)
问题:给你固定的算力预算(比如 $10^{23}$ FLOPs),怎么分配最好?
- 选项 A:训练一个 大模型(比如 500 亿参数),但只喂 少量数据(1 万亿 tokens)
- 选项 B:训练一个 中等模型(比如 67 亿参数),但喂 大量数据(1.5 万亿 tokens)
Chinchilla 的答案:
- 通过 scaling laws 实验发现:选项 B 更好
- 结论:模型大小和数据量要"配平",不能只做大模型
实际应用:
- DeepSeek 用 scaling laws 选了最优的 batch size(每次训练喂多少数据)和 learning rate(学习速度)
- 这样避免了盲目试错,省钱省时间
二、Prompting(提示工程)—— 不改模型,只改输入
1. Prompting 是什么?
本质:通过精心设计的"输入文本",让模型做你想做的事。
例子:
- 任务:情感分类(判断电影评论是正面还是负面)
- 不用 prompting:需要重新训练一个分类模型
- 用 prompting:直接问模型:
|
|
模型回答:positive
2. Prompting 的三个步骤
步骤 1:填充模板(Prompt Template)
把你的输入塞进一个"模板"里:
|
|
步骤 2:预测答案(Answer Prediction)
把 prompt 喂给模型,模型生成回答:
|
|
步骤 3:后处理(Post-processing)
从模型输出里提取你要的信息:
- 格式化:把结果渲染成表格、JSON
- 提取关键词:比如从"The answer is positive"里提取"positive"
- 映射:把"fantastic, great, awesome"都映射成"Positive"类别
3. Few-shot Prompting(少样本学习)
定义:在 prompt 里先给几个例子,让模型"看懂"你要做什么。
例子:
|
|
模型会根据前面的例子,推断出答案是 positive。
4. Few-shot 的"奇怪现象"
现象 1:有时候"不给答案"反而更好
- 实验发现:有些任务,只给输入(不给输出)效果更好
- 例子:
|
|
- 原因:模型可能在"检索任务",而不是真的在学习规律
现象 2:例子太多反而变差
- 实验:在某些任务上,4 个例子效果最好,10 个例子反而下降
- 原因:太多例子可能让模型"混乱"
现象 3:对例子的顺序非常敏感
- 实验:
- 顺序 A(正面、负面、正面、负面):准确率 85%
- 顺序 B(正面、正面、负面、负面):准确率 50%(接近随机)
- 结论:需要注意:
- 标签平衡:正负例数量要均衡
- 标签覆盖:多分类任务要覆盖所有类别
- 例子顺序:不同排列效果差异巨大
5. Prompt Engineering(提示工程)—— 怎么设计好的 prompt?
手动设计技巧
原则 1:格式要匹配模型训练时的格式
- 如果模型训练时是 chat 格式(system, user, assistant),就用 chat 格式
- 如果是纯文本补全,就用纯文本格式
原则 2:指令要清晰、具体
- ❌ 不好:
Explain prompt engineering. Keep it short. - ✅ 更好:
Use 2-3 sentences to explain prompt engineering to a high school student.
自动优化方法
方法 1:用 LLM 生成 prompt
- 让 GPT-4 帮你写更好的 prompt
- 例子(数学题任务):
- 手写 prompt:
Let's think step by step.(准确率 71.8%) - LLM 生成:
Take a deep breath and work on this problem step-by-step.(准确率 80.2%)
- 手写 prompt:
方法 2:Prompt Tuning(提示调优)
- 不优化"词",而是优化"词的 embedding(向量表示)"
- 模型参数冻结,只训练 prompt 的向量
方法 3:Prefix Tuning(前缀调优)
- 优化 Transformer 的 attention 层的 key 和 value 向量
- 比 prompt tuning 更灵活
6. 高级 Prompting 技巧
Chain-of-Thought (CoT)(思维链)
原理:让模型先"解释推理过程",再给最终答案。
例子:
|
|
效果:复杂推理任务(数学、逻辑)准确率显著提升。
Zero-shot CoT:甚至不用给例子,只要加一句 Let's think step by step.,模型就会自动推理。
Program-aided Language Models (PAL)
原理:让模型生成代码来计算答案,而不是直接生成数字。
例子:
|
|
优势:数值计算更精确,尤其复杂计算时。
Self-Ask(自我提问)—— 问题分解
原理:把复杂问题拆成多个子问题,逐步查询搜索引擎。
例子:
|
|
Prompt Chains(提示链)
原理:把多个模型调用"串联"起来。
例子:
|
|
三、Fine-tuning(微调)—— 改模型参数
1. 标准微调是什么?
流程:
- 拿一个预训练模型(比如 GPT-3)
- 在你的任务数据上继续训练
- 模型参数会调整,变得更适合你的任务
公式: $\min_\theta \sum_{(x,y) \in D} -\log p_\theta(y|x)$
- $x$:输入(比如论文正文)
- $y$:输出(比如摘要)
- 目标:最大化模型生成正确输出的概率
2. 微调的效果
好处:
- 数据高效:从预训练模型开始,只需少量任务数据
- 性能好:在特定任务上超越通用模型
坏处(分布收窄):
- 模型变"专一"了,泛化能力下降
- 症状:
- 摘要模型不会翻译了
- 模型强制要求特定格式(训练时的格式)
- Few-shot 能力消失(不能从几个例子学习新任务)
3. Instruction Tuning(指令微调)—— 让模型"多才多艺"
核心思想:不只训练一个任务,而是训练很多任务,每个任务都用"指令"格式。
数据格式:
|
|
关键发现(FLAN 论文):
- 训练 62 个 NLP 任务(翻译、分类、问答…)
- 测试时遇到没见过的新任务,模型也能做得不错
- 结论:指令微调让模型学会了"理解任务指令"的能力
4. 指令数据从哪来?
方法 1:从数据集改造(FLAN)
- 拿现有数据集(比如翻译数据)
- 用模板生成指令:
"Translate this to French: [input]"
方法 2:人工写(SuperNaturalInstructions)
- 众包标注:1600 个任务,每个任务人工写指令和例子
方法 3:让模型自己生成(Self-Instruct)
- 用 GPT-3 生成 50,000+ 条指令数据
- 流程:
- 给模型几个种子指令
- 让模型生成新指令
- 让模型根据指令生成输入和输出
- 用生成的数据训练模型
5. Chat Tuning(对话微调)
目标:训练一个"聊天机器人"。
数据格式:
|
|
System Prompt 例子(Claude 3.5):
|
|
6. Knowledge Distillation(知识蒸馏)—— 用"好学生"教"差学生"
核心思想:用一个强大的模型(teacher,比如 GPT-4)来训练一个小模型(student,比如 7B 模型)。
Token-level 蒸馏
- 目标:学生模型学习教师模型的"概率分布"
- 公式:
$\min KL(q(y|x) \| p_\theta(y|x))$
- $q(y|x)$:教师模型的输出分布
- $p_\theta(y|x)$:学生模型的输出分布
- 效果:学生模型学到"软标签"(不只是对错,还有概率)
Sequence-level 蒸馏
- 目标:学生模型在教师生成的数据上训练
- 流程:
- 用 GPT-4 生成大量高质量回答
- 用这些数据微调小模型
- 例子:
- Alpaca:用 GPT-3.5 生成 52k 条指令数据,训练 7B 模型
- Vicuna:用 ShareGPT 收集的真实 ChatGPT 对话,训练 13B 模型
7. 高效微调(省钱省显存)
问题:全参数微调太贵
- 例子:训练 65B 参数模型(16-bit)需要:
- 参数:130 GB
- 梯度:130 GB
- 优化器状态:260 GB
- 总计:520 GB 显存!
解决方案:LoRA(Low-Rank Adaptation)
原理:不训练所有参数,只训练一个"小的修正矩阵"。
公式: $W' = W + A \cdot B$
- $W$:原始权重矩阵(冻结,不训练)
- $A$:小矩阵($d \times r$),$r$ 很小(比如 8)
- $B$:小矩阵($r \times d$)
- $A \cdot B$:低秩矩阵,参数量远小于 $W$
例子:
- 原始矩阵 $W$:4096 × 4096 = 16M 参数
- LoRA 矩阵 $A, B$:(4096 × 8) + (8 × 4096) = 65k 参数
- 参数量减少 250 倍!
训练后:把 $A \cdot B$ 加到 $W$ 上,得到新模型,推理时无额外开销。
HydraLoRA(多任务优化版)
问题:一个 LoRA 训练多个任务,任务之间会"打架"(task interference)。
解决方案:
- 共享 A 矩阵:捕捉任务共性
- 多个 B 矩阵:每个任务一个 B,捕捉任务特性
- 效果:既减少参数,又提升多任务性能
四、Reinforcement Learning(强化学习)
为什么微调还不够?
问题 1:任务不匹配(Task Mismatch)
语言模型的目标:预测"最可能出现的下一个词"
|
|
我们真正想要的目标:
- 回答是否有用(helpful)
- 回答是否安全(non-toxic)
- 代码是否通过测试(correct)
矛盾:
- “最可能"的回答 ≠ “最有用"的回答
- 比如网上很多回答是错的、有毒的,但模型会学到
问题 2:数据不匹配(Data Mismatch)
训练数据的问题:
- Reddit 评论:包含大量有毒、攻击性内容
- GitHub 代码:很多代码有 bug
- 网页文本:很多错误信息
我们缺少的数据:
- 高质量的推理过程(思维链)
- 对所有问题的完美回答
- 完全正确的代码
问题 3:Exposure Bias(暴露偏差)
问题:模型训练时从未见过"自己犯错"的情况。
例子:
- 训练时:每一步都给正确答案
|
|
- 测试时:模型自己生成,可能第一步就错了
|
|
后果:模型不知道如何"纠错”,小错误会滚雪球。
强化学习怎么解决?
核心思想:让模型自己生成回答,然后用"奖励信号"告诉它好坏。
RL 的三个优势:
- 直接优化任务目标
- 不再是"预测下一个词”,而是"最大化 reward"
- Reward 可以是:代码通过测试、回答被人类点赞、对话达成目标
- 数据由模型生成
- 不依赖预先收集的数据
- 模型探索、犯错、学习,生成自己的训练数据
- 训练时见过错误
- 模型生成错误回答 → 得到负 reward → 学会避免
- 测试时遇到类似情况,知道怎么处理
RL 的流程(详细讲 RLHF)
|
|
五、总结:三个核心方法对比
| 方法 | 改变什么 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Prompting | 只改输入文本 | 无需训练,快速灵活 | 性能有限,敏感脆弱 | 快速原型,通用任务 |
| Fine-tuning | 改模型参数 | 性能好,数据高效 | 需要数据和算力,泛化下降 | 特定领域/任务 |
| RL | 用 reward 优化 | 直接优化目标,处理复杂任务 | 训练不稳定,需要设计 reward | 需要交互、多步决策 |
关键技巧速查表
Prompting 技巧
- ✅ 指令清晰具体
- ✅ 格式匹配模型训练
- ✅ Few-shot 注意标签平衡和顺序
- ✅ CoT:加
Let's think step by step - ✅ PAL:让模型生成代码计算
Fine-tuning 技巧
- ✅ Instruction tuning:多任务泛化
- ✅ 知识蒸馏:用强模型教弱模型
- ✅ LoRA:省显存(参数减少 100-250 倍)
- ✅ 注意分布收窄问题
RL 技巧
- ✅ 设计好 reward function
- ✅ 用于需要交互反馈的任务
- ✅ RLHF:结合人类反馈