0. 系列闭环
| 本篇位置 | 上游 | 本篇产出 | 下游 |
|---|---|---|---|
| 第 3/10 篇 | 第 02 篇数据进入模型 | 理解 r/alpha/target_modules | 第 05–06 篇 Trainer 配置 · 第 10 篇 vLLM --max-lora-rank |
读本篇后再打开 train_lora_single.py,看到 LoraConfig 不应再是「调参黑盒」。
1. 要解决的实际问题
全量微调 Qwen3.5-4B(约 4,216,368,128 参数)在单卡 V100 上:
- 优化器状态占用巨大,即使用 bf16 也紧张
- 每次实验保存 8GB+ checkpoint,迭代慢
- 1000 条对话数据相对 42 亿参数极易过拟合全量权重
LoRA 的核心承诺:只学「任务增量」ΔW,且 ΔW 低秩可分解,参数量降到千万级。
本项目实测(all_logs.log 第 34 行):
1 | |
2. 实现位置
| 文件 | 内容 |
|---|---|
LoRA_Demo/train_lora_single.py |
LORA_R、LORA_ALPHA、LoraConfig(...) |
LoRA_Demo/output/.../final_lora/adapter_config.json |
训练落盘后的 r=8, alpha=16, target_modules 列表 |
LoRA_Demo/output/.../final_lora/adapter_model.safetensors |
可训练权重本体(~41 MB) |
注意:LoRA 在 SFTTrainer(..., peft_config=lora_config) 创建时才注入,不是在 LoraConfig(...) 定义时。
3. 数学形式(对照代码)
对某线性层,原前向:
[
y = W x
]
LoRA(peft 默认):
[
y = W x + \frac{\alpha}{r} B A x
]
- (W):冻结,来自
AutoModelForCausalLM.from_pretrained - (A \in \mathbb{R}^{r \times k}),(B \in \mathbb{R}^{d \times r}):训练
- 代码里
LORA_R = 8→ (r=8) LORA_ALPHA = 16→ 缩放 (\alpha/r = 2)
1 | |
为什么低秩够用: 风格 SFT 改的是「怎么说」的条件分布,相对原模型是低维偏移;不需要动满秩 (W)。
4. 三个超参在本项目中的取值
4.1 LORA_R = 8
| r | 参数量 | 适用 |
|---|---|---|
| 4 | 更少 | 极窄任务、防过拟合 |
| 8 | 本项目 | 1000 条风格 SFT 平衡点 |
| 16+ | 更多 | 更复杂行为/多域,小数据慎用 |
vLLM 部署时必须 --max-lora-rank 8 与训练 r 一致(第 10 篇)。
4.2 LORA_ALPHA = 16
控制 LoRA 分支对输出的有效步长。不是越大越好:过大易震荡,过小学不动。16/8=2 是常见经验起点。
4.3 LORA_DROPOUT = 0.05
仅作用在 LoRA 分支。1000 条数据有重复句式,轻微 dropout 减轻死记。
5. target_modules:为什么在 attention + FFN 全注入
train_lora_single.py 第 189–192 行:
1 | |
Qwen3.5 每个 Transformer 层:
1 | |
| 模块组 | 影响 |
|---|---|
| Q/K/V/O | 注意力模式:关注 user 情绪词 vs 事实词 |
| gate/up/down | 前馈非线性:用词习惯、句式节奏 |
只注入 q_proj,v_proj 也能训,但风格迁移通常弱于** attention+FFN 全注入**。代价是参数量从百万级到千万级——对本项目仍仅 0.25%。
落盘验证(adapter_config.json):
1 | |
6. 与 SFTTrainer 的衔接(易错点)
正确写法
1 | |
错误写法
1 | |
重复注入会导致不可预期行为或报错。脚本注释(第 184、224 行)明确写了「勿重复 get_peft_model」。
训练前 trainer.model.print_trainable_parameters() 必须看到 **~0.25%**。若是 0% 或 100%,立刻停训查配置。
7. 有效 batch 与 LoRA 无关但决定步数
1 | |
总步数:
[
\text{steps} = \lceil 1000 / 4 \rceil \times 3 = 750
]
与 LoRA 无直接关系,但决定每条样本被看几遍、学习率调度长度。改 batch 不改 LoRA,却改训练动态。
8. 踩坑
坑 1:改 r 后不重新训练 adapter
旧 adapter 的 adapter_config.json 里 r=8,若手改脚本 r=16 再加载旧权重,shape 对不上。
坑 2:target_modules 拼写错一个字母
例如 q_projj,PEFT 静默不注入该层,trainable% 下降但不一定报错。
坑 3:以为 LoRA 省显存 = 可以任意增大 seq_len
LoRA 主要省可训练参数和优化器;前向仍要跑完整 4B 基座,512 token 的激活显存仍在。OOM 先减 BATCH_SIZE 或 MAX_SEQ_LEN(第 06 篇)。
坑 4:vLLM --max-lora-rank 小于训练 r
启动失败或静默降级;部署参数必须读 adapter_config.json 对齐。
9. 小结
- LoRA 冻结 (W),训练低秩 (BA),本项目仅 0.2518% 参数。
- r=8, alpha=16, dropout=0.05 写在脚本顶部,落盘在
adapter_config.json。 - 7 个 target_modules 覆盖 attention + FFN,适合风格 SFT。
- 只通过
SFTTrainer(peft_config=...)注入,不要重复get_peft_model。 - 部署时 vLLM 的 max-lora-rank 必须与 r 一致。
附录:LoraConfig 字段对照
1 | |
系列导航
| 篇目 | 链接 |
|---|---|
| 上一篇 | 02 · 训练集设计 |
| 下一篇 | 04 · 环境搭建 |
| 索引 | README |