第四章 模型微调与对齐
4.1 微调基础概念:为什么需要微调
承前:从 Prompt 到模型本身
在第三章中,我们花了大量篇幅学习提示工程——如何通过精心设计的 Prompt 让模型表现得更好。Prompt 工程确实强大,但它有一个根本限制:你只能改变"说什么",无法改变模型"是什么"。
打个比方:Prompt 工程就像给一个新员工写更好的工作说明书。说明书写得再好,如果这个员工本身不具备某项专业技能,你无法靠说明书让他学会。同样地,当一个预训练模型不知道你公司内部的业务术语、不了解特定领域的知识、或者输出风格始终不符合你的要求时,再怎么调 Prompt 也无济于事。
这时候,你需要微调——直接修改模型本身的参数,让它"学会"新的能力。
为什么预训练模型不够用?
想象一下,你招聘了一位博学多才的大学毕业生(预训练模型),他读过几乎所有的书,能背诵维基百科,但从未上过一天班。当你让他写一封商务邮件时,他可能会交出一篇优美的散文——方向对了,但格式不对、风格不对、不知道什么该说什么不该说。
预训练模型本质上是一个"下一个词预测器"(Next Token Predictor)。它在海量互联网文本上学会了语言的统计规律,但并不知道如何"遵循指令"或"完成特定任务"。
预训练模型的能力与局限:
┌─────────────────────────────────────────────┐
│ 预训练模型(Base Model) │
│ ✅ 世界知识:历史、科学、文化常识 │
│ ✅ 语言能力:语法、推理、多语言 │
│ ✅ 模式识别:类比、归纳、模式补全 │
│ ❌ 无法遵循指令格式 │
│ ❌ 不会拒绝有害请求 │
│ ❌ 缺乏特定领域知识(医学、法律等) │
│ ❌ 输出风格不可控 │
└─────────────────────────────────────────────┘微调(Fine-tuning)正是为了解决这些局限而存在的。它是连接"通用语言模型"与"实际可用助手"的关键桥梁。
微调的核心目标:在预训练模型的基础上,使用少量但高质量的数据,让模型学会特定行为模式——包括遵循指令格式、对齐人类偏好、掌握领域知识。
预训练 vs 微调:三阶段范式
现代大模型开发遵循经典的 "预训练-微调-对齐"三阶段范式。用教育来类比:预训练是"通识教育"(小学到大学),微调是"岗前培训",对齐是"职业道德教育"。
阶段一:预训练(Pre-training) = 通识教育
数据:数万亿 Token 互联网文本 = 读遍图书馆
成本:数千万美元 = 国家级投入
目标:学习语言的统计规律 = 学会读书写字
输出:Base Model(基座模型) = 毕业生
↓
阶段二:监督微调(SFT) = 岗前培训
数据:数万~数十万条指令-回答对 = 培训手册
成本:数百~数千美元 = 公司培训成本
目标:教会模型遵循指令格式 = 学会做事
输出:Chat Model(对话模型) = 合格员工
↓
阶段三:偏好对齐(Alignment) = 职业道德教育
数据:数千~数万条人类偏好对比数据 = 师徒制反馈
成本:数百~数千美元 + 标注成本 = 导师时间
目标:让模型输出更符合人类价值观 = 学会做人
输出:Aligned Model(对齐模型) = 优秀员工关键区别:
| 维度 | 预训练 | 微调(SFT) | 对齐(RLHF/DPO) |
|---|---|---|---|
| 数据量 | TB 级 | MB~GB 级 | KB~MB 级 |
| 数据格式 | 纯文本 | 指令-回答对 | 偏好对比对 |
| 训练目标 | 下一个词预测 | 下一个词预测 | 最大化奖励/偏好 |
| 计算成本 | 极高 | 中等 | 中高 |
| 知识注入 | 是 | 少量 | 极少 |
| 行为塑造 | 否 | 是 | 是(更深层) |
全量微调 vs 参数高效微调(PEFT)
当谈到微调的具体实施方式时,一个核心问题是:更新多少参数?
💡 类比:全量微调就像"让员工重新读一遍大学",每个知识点都重新学;PEFT 就像"只给员工补几门专业课",基础知识不变,只学新东西。
全量微调(Full Fine-tuning) 更新模型的所有参数。对于 Llama-3-8B 这样的模型,这意味着更新全部 80 亿个参数。优点是理论上效果最好,但缺点也很明显:显存需求巨大(8B 模型需约 64GB 以上显存),且每个任务需要保存一份完整模型副本。
参数高效微调(PEFT) 的核心理念是:冻结大部分预训练参数,只更新极少量的额外参数。以 LoRA 为例,它只新增一个低秩矩阵(通常不到 1% 的参数),却能接近全量微调的效果。QLoRA 进一步引入 4-bit 量化,可以在单张 24GB 消费级显卡上微调 70B 模型。
📌 PEFT 的详细原理和代码实战将在 4.3 节展开,这里只需知道它的定位:以极低成本达到接近全量微调的效果。
微调数据准备
数据准备是微调中最耗时但最重要的环节。一个常被引用的经验法则是:"垃圾进,垃圾出"(Garbage In, Garbage Out)。
数据质量遵循一个金字塔结构:人工精心标注的"黄金数据"效果最好但成本最高;纯模型生成的"铁质数据"成本最低但质量也最低。实际项目中,通常混合使用不同质量层级的数据。
数据准备的核心原则:
- 多样性:覆盖不同任务类型(问答、摘要、翻译、代码、推理等)
- 高质量:一条坏数据可能抵消十条好数据的效果
- 格式一致性:统一使用选定的对话模板(ChatML / ShareGPT / Alpaca)
- 长度适中:过长的样本会撑爆显存,过短则信息量不足
- 去噪去重:移除重复、矛盾、模糊不清的样本
| 场景 | 建议数据量 | 说明 |
|---|---|---|
| 指令遵循(通用) | 10K~50K 条 | 让模型学会对话格式 |
| 特定领域适配 | 1K~10K 条 | 注入领域知识 |
| 风格迁移 | 500~2K 条 | 改变输出风格 |
| 简单任务微调 | 100~500 条 | 格式转换等简单任务 |
实战:分析微调数据集
下面用 Python 分析一个真实的指令微调数据集,理解其结构:
from datasets import load_dataset
import json
# 加载 Alpaca 中文数据集(指令微调格式)
dataset = load_dataset("silk-road/alpaca-data-gpt4-chinese", split="train")
print(f"数据集大小: {len(dataset)} 条") # 打印总条数
# 查看第一条数据的结构
print(f"\n第一条数据:")
print(json.dumps(dataset[0], ensure_ascii=False, indent=2))
# 典型字段:instruction(指令)、input(输入,可选)、output(期望输出)
# 分析指令和输出的长度分布
instruction_lengths = [len(item['instruction']) for item in dataset]
output_lengths = [len(item['output']) for item in dataset]
print(f"\n统计信息:")
print(f" 指令平均长度: {sum(instruction_lengths)/len(instruction_lengths):.0f} 字符")
print(f" 输出平均长度: {sum(output_lengths)/len(output_lengths):.0f} 字符")
print(f" 指令长度范围: {min(instruction_lengths)} - {max(instruction_lengths)}")
print(f" 输出长度范围: {min(output_lengths)} - {max(output_lengths)}")
# 数据质量检查——空指令或空输出是常见的数据问题
empty_instructions = sum(1 for item in dataset if not item['instruction'].strip())
empty_outputs = sum(1 for item in dataset if not item['output'].strip())
print(f"\n质量检查:")
print(f" 空指令数: {empty_instructions}") # 应为 0
print(f" 空输出数: {empty_outputs}") # 应为 0常见误区
⚠️ 误区一:"微调能注入大量新知识" 微调适合教模型"行为模式"(格式、风格、拒绝策略),不适合注入大量事实知识。如果要注入知识,RAG(第6章)通常更有效。
⚠️ 误区二:"数据越多越好" 1000 条高质量数据的效果通常优于 10000 条噪音数据。数据质量远比数量重要。
⚠️ 误区三:"微调后就不需要 Prompt 工程了" 微调和 Prompt 工程是互补的。微调让模型"更听话",好的 Prompt 让模型"更精准"。即使微调后,精心设计的 Prompt 仍然能显著提升效果。
⚠️ 误区四:"微调就是继续训练" 预训练是"学语言",微调是"学格式和行为"。两者的数据格式、训练目标、超参数都不同。直接用预训练的方式继续训练,效果会很差。
⚠️ 误区五:"微调一定比 Prompt 工程好" 如果 Prompt 能解决的问题,就不应该用微调。微调有数据准备成本、训练成本、维护成本。优先尝试 Prompt → RAG → 微调,这是经济性递减的顺序。
本节小结
| 要点 | 说明 |
|---|---|
| 微调的必要性 | 预训练模型是"通用语言引擎",微调将其转化为"任务专用助手" |
| 三阶段范式 | 预训练(知识获取)→ SFT(格式学习)→ 对齐(价值观塑造) |
| 全量 vs PEFT | 全量微调效果好但成本高;PEFT 以极低成本达到接近效果 |
| 数据为王 | 数据质量远比数量重要,1000 条高质量 > 10000 条噪音 |
| 格式统一 | 数据格式必须与模板一致,否则会导致训练失败 |
| 优先级 | Prompt → RAG → 微调,按成本从低到高尝试 |
启后
理解了微调的基本概念后,下一节我们将深入 SFT(监督微调)的具体实现——如何构建指令数据集、如何配置训练参数、如何评估微调效果。SFT 是微调中最常用的方法,也是后续 RLHF 和 DPO 的基础。