10. 微调:从 Full Fine-tuning 到 LoRA/QLoRA
- 区分 CPT、SFT、LoRA 与 QLoRA
- 解释低秩更新和 target modules
- 用固定题集比较 Base 与 Adapter
- 模型前向与优化
- 训练/验证/测试切分
本章产物LoRA Adapter、训练日志和前后逐题评估。
10.1 预训练、继续预训练和 SFT
| 阶段 | 数据 | 学到什么 |
|---|---|---|
| Pretraining | 大量普通 token 序列 | 通用语言、知识和模式 |
| Continued Pretraining/CPT | 领域无标注文本 | 领域语言与分布 |
| SFT | 指令—回答或多轮对话 | 指令遵循、格式、任务行为 |
| Preference Optimization | chosen/rejected 或奖励 | 行为偏好与对齐 |
如果目标是让模型学习大量领域术语和文体,CPT 可能比只做问答 SFT 更合适;如果目标是固定输入输出行为,SFT 更直接。
10.2 Full Fine-tuning 为什么贵
Full fine-tuning 更新全部参数,因此需要:
- 全部参数梯度。
- 全部参数的优化器状态。
- 反向传播激活。
对于多个任务,还需要分别保存完整模型。LoRA 通过冻结基础权重,只训练少量低秩更新,降低训练和存储成本。
10.3 LoRA 的数学
原线性层:
y = x W^T微调希望学习:
W' = W + ΔWLoRA 假设更新近似低秩:
ΔW = B A若 W 形状 [d_out, d_in],秩 r:
A: [r, d_in]
B: [d_out, r]完整更新参数:
d_out × d_inLoRA 参数:
r × (d_in + d_out)当 r 远小于维度时,差异巨大。
配套实验:从零实现 LoRA Notebook。实验验证参数冻结、低秩增量训练和部署前权重合并。
常见缩放:
y = xW^T + (alpha / r) × xA^T B^T运行:
python code/05_lora_from_scratch.py代码将 B 初始化为 0,使训练开始时 LoRA 分支输出为 0,模型初始行为与基础层一致。
10.4 target_modules 怎样选
常见目标:
q_proj,k_proj,v_proj,o_proj- MLP 的
gate_proj,up_proj,down_proj
只调 Q/V 参数更少;调全部线性层适应能力更强但内存和存储更大。最佳选择取决于任务和模型,不能把某个博客配置当普遍定律。
关键超参数:
r:低秩维度。lora_alpha:缩放。lora_dropout:适度正则。target_modules:注入位置。- learning rate:LoRA 常比 full fine-tuning 使用更高学习率。
10.5 QLoRA
QLoRA:
冻结的基础模型:4-bit 量化
可训练部分:LoRA adapter
梯度:穿过量化基础模型,更新 adapter它不是“直接训练 4-bit 基础权重”。原论文还引入 NF4、double quantization 和 paged optimizer 等内存优化。
在 NVIDIA 上常见 bitsandbytes + PEFT;在你的 Mac 上更适合使用 MLX-LM 对量化 MLX 模型训练 adapter。不要强行安装 CUDA 专用教程里的 bitsandbytes 路线。
10.6 SFT 数据格式
资料包 data/sft_train.jsonl:
{"messages":[
{"role":"system","content":"你是一位耐心的老师。"},
{"role":"user","content":"什么是 token?"},
{"role":"assistant","content":"……"}
]}高质量 SFT 数据应:
- 输入符合真实使用分布。
- 输出风格与标准一致。
- 事实正确、边界清楚。
- 包含困难样本、拒答样本和格式样本。
- 去重并划分 train/validation/test。
- 不把测试答案泄漏到训练。
一万条高质量、针对性强的数据,可能比百万条模板化垃圾数据更有价值。
10.7 在 Qwen3-0.6B 上做 LoRA SFT
python code/06_sft_lora.py \
--model Qwen/Qwen3-0.6B \
--data data/sft_train.jsonl \
--epochs 1这是流程演示数据,只有几条,不能用于得出能力结论。正式实验至少:
- 划分验证和测试集。
- 训练前先评估 base model。
- 固定评估 prompt 和采样。
- 观察 train/validation loss。
- 对 adapter 后模型运行同一评估。
- 人工检查是否出现灾难性遗忘、格式过拟合和错误自信。
若当前 TRL 版本更新了参数名,优先以安装版本的 SFTConfig 帮助和官方文档为准:
python -c "from trl import SFTConfig; help(SFTConfig)"10.8 使用 MLX-LM LoRA/QLoRA
python -m pip install "mlx-lm[train]"
mkdir -p artifacts/mlx-data
cp data/sft_train.jsonl artifacts/mlx-data/train.jsonl
mlx_lm.lora \
--model mlx-community/Qwen3-0.6B-4bit \
--train \
--data artifacts/mlx-data \
--iters 100MLX-LM 要求数据目录按其文档放置 train.jsonl,可选 valid.jsonl,测试时使用 test.jsonl。当模型本身为量化模型时,其训练路线属于 QLoRA。
不要因为 48GB 能装下大模型就立刻对 32B 做 LoRA。先用 0.6B 验证数据格式、loss mask、保存和评估,再逐步扩大。
10.9 过拟合、灾难性遗忘与风格塌缩
- 过拟合:记住训练答案,验证效果下降。
- 灾难性遗忘:领域适配后,原有通用能力明显下降。
- 风格塌缩:任何问题都套用同一种格式或长篇模板。
- 数据回声:模型复述训练数据中的固定短语。
应对:
- 更好的数据划分和去重。
- 更低学习率、更少 epoch、更早停止。
- 混入一定比例通用数据。
- 降低 LoRA rank 或缩小 target modules。
- 不只看 loss,使用多维评估。
10.10 动手:把 SFT 做成前后可比较的实验
实验 06|LoRA/SFT 资源:0.6B 模型建议 8GB 以上可用内存;时间取决于设备与下载;产物:数据切分、base 结果、Adapter、训练日志和 adapter 结果。
不要从训练命令开始。先准备固定评测文件 data/sft_eval.jsonl,每条至少包含:
{"id":"format-001","messages":[{"role":"user","content":"以 JSON 返回两个字段"}],"required":["answer","reason"]}完整顺序:
- 对
sft_train.jsonl去重并按任务族切分,防止同模板跨集合泄漏。 - 固定 20~100 条小型评测集,训练前保存 base model 的逐题原始输出。
- 运行一次小规模 LoRA,确认 loss、显存和 Adapter 保存路径正常。
- 用同一 prompt template、采样参数和评测代码生成 adapter 输出。
- 对比格式通过率、任务正确率、拒答、安全和通用保留集;逐条保存变化。
训练冒烟命令:
python code/06_sft_lora.py \
--model Qwen/Qwen3-0.6B \
--data data/sft_train.jsonl \
--output artifacts/checkpoints/qwen3-06b-lora-smoke \
--epochs 0.1训练报告不能只贴最后一个 loss。至少填写:
| 证据 | Base | Adapter | 解释 |
|---|---|---|---|
| 格式通过率 | 是否真正学会目标格式 | ||
| 目标任务正确率 | 逐题判分规则是什么 | ||
| 通用保留集 | 是否发生明显遗忘 | ||
| validation loss | 是否与 train loss 同向 | ||
| 峰值内存与耗时 | 模型、设备和 dtype |
停止条件:如果训练数据只有几条演示样本,可以验收“流程可运行”,但不得写出“能力提升”的结论。如果 Adapter 只让所有答案套用统一模板,应归类为风格过拟合,而不是对齐成功。
先执行数据切分和泄漏检查:
python code/10_prepare_sft_data.py \
--input data/sft_train.jsonl \
--output-dir artifacts/sft-data脚本按 prompt group 切分,而不是随机按行切分。若数据少于三个独立 group,它会发出警告;这时只能验证流程,不能声称验证集具有统计意义。
偏好优化使用独立的 preference JSONL:
python code/13_dpo_lora.py \
--data data/preference_train.jsonl \
--dry-run--dry-run 会校验 chosen/rejected 数据契约但不下载模型;确认数据、版本和资源后,再去掉该参数执行真实 DPO。真实训练必须把 reference model、β、chat template、prompt mask 和独立评估集写入报告。
本章依据
原理性结论以原始论文、官方文档或公开教材为依据。论文中的实验结果只适用于其声明的模型、数据、硬件和评估设置。
冻结基座权重并训练低秩增量矩阵。
4-bit 冻结基座、NF4、双重量化和分页优化器。
LoRA Adapter 的配置、训练、保存和合并接口。
Apple Silicon 上量化模型使用 QLoRA、数据格式与 Adapter 工作流。