LoRA 微调 Qwen3.5-9B:四轮实战参数调优攻略

LoRA 微调 Qwen3.5-9B:四轮实战参数调优攻略

基于真实训练日志提炼的"决策树"式调参指南


一、四轮实验全景总览

轮次 学习率 Epochs 数据量/份 梯度裁剪 Warmup 最终 Loss 最佳 Loss Token Acc 结论
R1 1e-4 1 #100 0.05 1.38 1.22 67% ❌ 梯度爆炸
R2 2e-5 3 #100 ✅ 1.0 0.1 1.33 1.19 68% ⚠️ 学不动
R3 5e-5 3 #200 ✅ 1.0 0.1 1.14 0.897 73.6% ✅ 最优
R4 3.5e-5 4 #200 ✅ 1.0 0.1 1.14 0.911 73.6% ➖ 边际递减

二、逐轮深度拆解:每轮改了什么?为什么改?结果如何?

🔴 第一轮:基线测试(踩坑)

训练命令关键参数:

复制代码
--learning_rate 1e-4
--num_train_epochs 1
--dataset #100
--warmup_ratio 0.05
# 无 gradient_clipping

日志核心数据:

Step Loss grad_norm Token Acc 学习率
1 1.23 NaN 68.1% 1e-4
5 1.47 NaN 65.4% 8.83e-5
10 1.54 1.91 64.1% 5e-5
15 1.33 0.67 66.1% 1.17e-5
19 1.38 - 67.0% -

❌ 问题诊断:

  1. 梯度爆炸:Step 1 和 Step 5 的 grad_norm: NaN,原因是学习率 1e-4 对 LoRA 来说太高 + 没有梯度裁剪保护,FP16 精度下数值溢出。

  2. 严重欠拟合:只跑了 1 个 Epoch(19 步),模型刚看完一遍数据就停了,Loss 停留在 1.38 高位,Token Acc 只有 67%。

  3. 预热不足:warmup_ratio=0.05 只有约 1 步预热,完全不足以让模型平稳起步。

✅ 学到的教训:

  • 必须加 --gradient_clipping 1.0(护身符)

  • 至少跑 3 个 Epoch(1 轮纯属浪费钱)

  • 提高 --warmup_ratio 到 0.1


🟡 第二轮:矫枉过正(保守治疗)

训练命令关键修改:

复制代码
--learning_rate 2e-5           # 从 1e-4 降到 1/5
--num_train_epochs 3           # 从 1 升到 3
--warmup_ratio 0.1             # 从 0.05 升到 0.1
--gradient_clipping 1.0        # 新增!
--torch_dtype bfloat16         # 从 float16 改为 bfloat16

日志核心数据:

Step Loss grad_norm Token Acc 学习率
1 1.23 1.42 ✅ 68.1% 3.33e-6
20 1.27 0.69 67.5% 1.65e-5
30 1.32 0.64 65.9% 1.09e-5
40 1.24 0.71 67.5% 5e-6
57 1.33 - 65.1% -

⚠️ 问题诊断:

  1. 梯度爆炸已彻底治愈:Step 1 的 grad_normNaN 变成了健康的 1.42,证明梯度裁剪 + 降学习率 + 预热组合拳有效。

  2. 学习率太低:2e-5 虽然安全,但模型"学不动"。Loss 在 1.2~1.3 区间徘徊了整整 3 个 Epoch,就是跌不破 1.2。

  3. 数据量太少:#100 每份只有 300 条总数据,模型 3 轮看完也没学到足够丰富的表达。

✅ 学到的教训:

  • 梯度裁剪治好了 NaN,但学习率需要往上提

  • 数据量要加大:#100 → #200 起步


🟢 第三轮:黄金交点(最优突破)

训练命令关键修改:

复制代码
--learning_rate 5e-5           # 从 2e-5 升到 5e-5
--num_train_epochs 3           # 保持 3
--dataset #200                 # 从 #100 升到 #200
--gradient_clipping 1.0        # 保留
--warmup_ratio 0.1             # 保留

日志核心数据:

Step Loss grad_norm Token Acc 学习率 备注
1 1.50 1.60 ✅ 63.2% 4.17e-6 起步平稳
30 1.12 0.60 69.2% 4.63e-5 首次跌破 1.2
60 1.04 0.69 70.4% 2.73e-5 持续下降
105 0.897 0.85 73.6% 9.5e-7 全局最优!
114 1.14 - 72.7% - 最终

✅ 成功诊断:

  1. 学习率 5e-5 是 LoRA 的"甜点区":既不会爆炸(有梯度裁剪兜底),又能让模型有足够的"动力"去优化。

  2. 数据量 #200(总计 600 条)刚好让模型吃饱:3 个 Epoch 的步数从 57 步增加到 114 步,给了模型充分的迭代空间。

  3. 最佳 Checkpoint 出现在总步数的 92% 处(105/114):说明模型在第 3 轮中后期达到最优,最后几步略有波动(学习率衰减到接近 0)。

  4. Token Acc 首次突破 70%,达到 73.6%:这是从"及格"到"优良"的分水岭。

✅ 策略启示:

  • 3 个 Epoch + 5e-5 + #200 = 黄金组合

  • 不要只看最终 Checkpoint,去日志里找 Loss 最低的那一行


🔵 第四轮:探索极限(边际递减)

训练命令关键修改:

复制代码
--learning_rate 3.5e-5         # 从 5e-5 降到 3.5e-5
--num_train_epochs 4           # 从 3 升到 4
# 其他全部保持不变

日志核心数据:

Step Loss grad_norm Token Acc 学习率 备注
105 0.911 0.91 73.3% 9.34e-6 全局最优(接近 R3 的 0.897)
152 1.14 - 73.6% - 最终

➖ 问题诊断:

  1. 边际收益递减:多跑 1 个 Epoch(+38 步)只把最终 Acc 从 72.7% 提到了 73.6%,但 Loss 没改善。

  2. 学习率 3.5e-5 偏保守:虽然全程稳定,但收敛速度比 5e-5 慢,到 Step 105 才达到 R3 Step 105 的水平(0.911 vs 0.897),略逊一筹。

  3. 4 个 Epoch 没有额外收益:模型在 600 条数据上的"学习能力"已经饱和,再多的 Epoch 也只是在重复记忆。

✅ 策略启示:

  • 3 个 Epoch 是最优性价比,4 个不划算(耗时 +33%,收益几乎为 0)

  • 学习率 5e-5 优于 3.5e-5:收敛更快,最优 Loss 更低


三、核心结论:参数决策树

🎯 学习率选择决策树

复制代码
训练起步
    │
    ├─ 加上 gradient_clipping=1.0 + warmup_ratio=0.1
    │
    ├─ 从 5e-5 开始(LoRA 黄金起点)
    │
    ├─ 观察 Step 1~5 的 grad_norm
    │   ├─ 如果是 NaN → 降到 3e-5,重跑
    │   └─ 如果是正常数字(0.5~2.0)→ 继续
    │
    └─ 观察 Epoch 1 结束时(总步数/3)的 Loss
        ├─ 如果 Loss < 1.2 → ✅ 保持 5e-5,完美
        ├─ 如果 Loss > 1.3 → 学习率太低,提到 8e-5
        └─ 如果 Loss 震荡剧烈 → 学习率太高,降到 3e-5

🎯 Epoch 数量选择决策树

复制代码
训练启动(learning_rate=5e-5,数据量#200)
    │
    ├─ 观察第 3 轮中后期(约总步数 70%~80%)的 Loss
    │   ├─ 如果 Loss 仍在明显下降(每 5 步降 > 0.05)→ 需要第 4 轮
    │   └─ 如果 Loss 已趋平或开始反弹 → 第 3 轮就是最优
    │
    └─ 你的数据证明:3 轮刚好,4 轮边际递减

🎯 数据量选择决策树

复制代码
数据量决定模型能学多“宽”
    │
    ├─ #100(300 条总数据)→ 只能死记硬背,Acc ≤ 68%
    ├─ #200(600 条总数据)→ 学会基础表达,Acc 73%~75%  ✅ 你在这里
    ├─ #500(1500 条总数据)→ 泛化能力增强,Acc 有望 78%~80%
    └─ 注意:数据量增加 → 步数增加 → 训练时间线性增长

四、"三步调参法"------小白直接套用

第一步:定底盘(不管什么模型都加上)

复制代码
--gradient_clipping 1.0
--warmup_ratio 0.1
--torch_dtype bfloat16      # 或 float16
--target_modules all-linear
--gradient_accumulation_steps 16

第二步:定起点(推荐起始值)

复制代码
--learning_rate 5e-5
--num_train_epochs 3
--dataset #200

第三步:看日志调优

日志现象 对策
Step 1 的 grad_norm = NaN 降到 learning_rate=3e-5 或确认 gradient_clipping=1.0 已加
Epoch 1 结束 Loss > 1.3 learning_rate8e-5
Epoch 2 结束 Loss > 1.0 升数据量到 #500
Epoch 3 结束 Loss < 0.6 过拟合了!降 Epoch 到 2
最佳 Loss 出现在 70%~80% 处 就用那个 Checkpoint,不要用最后一步

五、最终验收标准

基于实际的四轮数据,可以得出"合格/优良/优秀"三级标准:

等级 Loss(最低点) Token Acc 对话表现
合格 ≤ 1.2 ≥ 68% 能正确自我介绍,偶尔语序颠倒
优良 ≤ 1.0 ≥ 72% 流畅自我介绍,通用问答逻辑通顺
优秀 ≤ 0.8 ≥ 78% 表达自然,能处理多种问法变体