大模型微调
大模型微调完全指南:从数学原理到工程实战
完整记录低秩(LoRA)原理、过拟合欠拟合画像、核心训练参数调优、以及对齐技术(SFT/RLHF/DPO)的全链路知识体系。
第一部分:底层数学基石——低秩(Low Rank)
1.1 什么是“秩”?
在矩阵中,“秩”(Rank)代表矩阵列(或行)向量的最大线性无关组个数,也就是矩阵能表达的独立信息维度。
- 满秩矩阵:信息密度高,毫无冗余,无法压缩(如随机噪声)。
- 低秩矩阵:矩阵内部存在大量线性相关性,数据高度冗余,可以用极少的基向量线性组合还原。
1.2 在 LoRA 中的应用
核心公式:ΔW = B × A
W:原始权重矩阵(如10000 × 20000,冻结不动)B:10000 × 5的低秩矩阵A:5 × 20000的低秩矩阵- 中间的
5就是秩r,它充当“信息瓶颈”。
参数量对比:
| 场景 | 可训练参数量 | 说明 |
|---|---|---|
| 全量微调 | 10000 × 20000 = 2亿 |
需要巨大显存 |
| LoRA 微调 | (10000×5) + (5×20000) = 15万 |
减少 1300 多倍! |
第二部分:过拟合与欠拟合——AI的心理画像 🎭
2.1 过拟合(Overfitting)= 强迫症
- 特征:训练集 100 分,测试集 40 分(死记硬背,换题就懵)。
- 成因:LoRA 的
r值设得太大,或数据太少、训练轮数过多。 - 解法:降低
r、增加 Dropout、早停。
2.2 欠拟合(Underfitting)= 学渣
- 特征:训练集 30 分,测试集 25 分(稳定地差,啥也没学会)。
- 成因:LoRA 的
r值设得太小(如 1),或学习率太低。 - 解法:增大
r、增加 Epochs。
第三部分:核心训练参数详解(工程师操作面板) ⚙️
3.1 Batch Size(批次大小)——“卡车载重量”
- 定义:模型一次更新参数时同时“吃进去”的样本条数。
- 注意:受限于显卡显存。
- 公式:
1 个 Epoch 的总步数 = 数据总条数 ÷ Batch Size。 - 比喻:卡车一次拉 4 箱货,需要跑 250 趟才能拉完 1000 箱。
3.2 Epochs(训练轮数)——“复习遍数”
- ⚠️ 重大误区:增加 Epochs ≠ 增加新数据。Epochs 是把同一本练习册反复做 N 遍;增加数据才是买不同版本的练习册。
- 新手默认:
3 ~ 5轮。
3.3 max_steps(最大步数)——“紧急制动闸”
- 核心规则:如果同时设置
num_train_epochs=5和max_steps=30,后者拥有**“一票否决权”**,训练在第 30 步直接停止,无视 Epochs。 - 建议:正式训练时删掉
max_steps,仅在调试代码时使用。
3.4 LoRA 专用参数
| 参数 | 推荐值 | 比喻 | 作用 |
|---|---|---|---|
r(秩) |
8~16 | 手术刀精细度 | 控制参数量,r 太小变学渣,r 太大变强迫症 |
alpha |
16(= r) | 手术力度 | 控制 LoRA 影响大小,实际缩放 = alpha/r |
| target_modules | ["q_proj", "v_proj"] |
手术部位 | 决定插在模型哪个位置 |
| Dropout | 0.0~0.1 | 随机失忆 | 数据少时调高防过拟合 |
3.5 梯度累积(Gradient Accumulation)——“蚂蚁搬家”
- 公式:
有效 Batch Size = per_device_batch_size × gradient_accumulation_steps。 - 案例:物理 BS=4,累积步数=4 → 等效 BS=16(先欠着梯度,攒够 4 次再统一更新)。
- 注意:累积步数不要超过 8~16,否则模型长期不更新容易“跑偏”。
第四部分:对齐技术全家桶(SFT / RLHF / DPO)🚀
4.1 SFT(监督微调 / 指令微调)
- 本质:在大模型语境下,SFT ≈ 指令微调。它是所有下游微调的起点。
- 作用:语文老师,教模型“听懂人话”,纠正语法格式。
- 缺陷:只解决“答非所问”,无法解决“三观不正”(SFT 数据里几乎没有“拒绝回答”的样本)。
4.2 DPO(直接偏好优化)——“拉差距”的数学艺术
- 核心操作:不用复杂的强化学习,直接用
chosen(好回答)和rejected(坏回答)文本对,拉大两者间的对数概率差值。 - 重点澄清 1(打分):数据里没有分数!分数是模型前向传播时自己算出来的(对数概率)。DPO 只管把“好回答”的分数往上抬,把“坏回答”的分数往下踩。
- 重点澄清 2(防止遗忘):引入冻结的参考模型(Reference Model) 作为锚点。只允许在旧模型附近微调,保护通用知识不被误伤(调节参数
beta控制力度)。 - 对比 RLHF:显存消耗小、训练稳定,是个人开发者替代 PPO 算法的首选。
第五部分:前向传播与反向传播 🔄
| 维度 | 前向传播 | 反向传播 |
|---|---|---|
| 做什么 | 推理 / 预测(做题) | 学习 / 纠错(听老师评卷) |
| 数据流向 | 输入 → 输出(单向向前) | 输出(损失)→ 输入(反向倒推) |
| 是否修改模型 | ❌ 不改(权重冻结) | ✅ 改(更新权重) |
🎯 新手必记参数速查表(抄作业版)
| 参数类别 | 参数名称 | 推荐值 | 一句话作用 |
|---|---|---|---|
| 数据流 | Batch Size | 4~8(24G显存) | 卡车一次拉几箱货 |
| Epochs | 3~5 | 把练习册做几遍 | |
| max_steps | 不设(正式训练) | 紧急制动闸,优先级最高 | |
| LoRA | r(秩) |
16 | 手术刀精细度 |
alpha |
16 | 手术力度 | |
target_modules |
["q_proj", "v_proj"] |
手术部位 | |
| 训练节奏 | Learning Rate | 1e-4(LoRA) | 油门深度 |
| 梯度累积 | 4(显存不够时) | 蚂蚁搬家 | |
| Weight Decay | 0.01 | 防漂移限制器 | |
| 对齐 | DPO beta | 0.1 | 遗忘与对齐的平衡 |
个人开发者最佳路径:基座模型 → SFT(使用 LoRA 高效微调) → DPO(轻量级对齐) → 部署推理。
流程图:
flowchart LR
用户 --> 检索
检索 --> 权限过滤
权限过滤 --> 生成
公式:
行内 $E = mc^2$,独立一行:
$$
\mathrm{Cost} = \frac{n_{\mathrm{in}} P_{\mathrm{in}} + n_{\mathrm{out}} P_{\mathrm{out}}}{10^6}
$$
flowchart TD
A[用户下单] --> B{库存是否充足?}
B -- 否 --> C[提示缺货]
C --> D{是否接受预售?}
D -- 是 --> E[创建预售订单]
D -- 否 --> F[取消订单]
E --> G[等待补货]
G --> H[通知用户发货]
B -- 是 --> I[锁定库存]
I --> J[生成支付单]
J --> K{支付是否成功?}
K -- 否 --> L{是否超时?}
L -- 否 --> M[等待用户支付]
M --> K
L -- 是 --> N[释放库存]
N --> F
K -- 是 --> O[扣减库存]
O --> P[生成物流单]
P --> Q[通知仓库拣货]
Q --> R[出库发货]
R --> S[更新订单状态]
S --> T[通知用户已发货]
H --> S
flowchart LR
subgraph 客户端层
A1[Web 前端]
A2[移动 App]
A3[小程序]
end
subgraph 网关层
B1[API Gateway]
B2[鉴权中心]
B3[限流熔断]
end
subgraph 服务层
C1[用户服务]
C2[订单服务]
C3[支付服务]
C4[库存服务]
C5[通知服务]
end
subgraph 数据层
D1[(MySQL 主库)]
D2[(Redis 缓存)]
D3[(MQ 消息队列)]
D4[(Elasticsearch)]
end
A1 --> B1
A2 --> B1
A3 --> B1
B1 --> B2 --> B3
B3 --> C1
B3 --> C2
B3 --> C3
B3 --> C4
C1 --> D1
C1 --> D2
C2 --> D1
C2 --> D3
C3 --> D1
C3 --> D3
C4 --> D1
C4 --> D2
D3 --> C5
C5 --> A1
C2 --> D4
flowchart TD
subgraph Main[主流程]
A[开始] --> B{判断}
B -- 是 --> C[处理]
B -- 否 --> D[结束]
end