多模态微调实战(09):踩坑与经验清单
把这次实践里真正耗时间的坑集中写在这里,方便检索。环境依赖、GPU 被静默占用、评测口径、全量运维、合并导出、量化——每一类都有几个反复出现的问题。
这是「多模态微调实战」的第 09 篇。前八篇讲「怎么做对」,这一篇讲「哪里容易做错」。
一、环境与依赖
1.1 datasets 版本冲突
现象:训练启动时报奇怪的 ImportError / JSON 相关错误。
处理:把 datasets 固定到与当前 ms-swift 匹配的范围(实践中用过 >=4.4,<4.8.5),并写进镜像或启动脚本。
1.2 没有 flash-attn
现象:--attn_impl flash_attn 直接失败。
处理:改用 --attn_impl sdpa,先求稳。
1.3 DeepSpeed / mpi4py
现象:单卡强行上 deepspeed 反而更麻烦。
处理:16GB 单卡 LoRA + 梯度检查点通常够用;深造优化留给真的多卡或更大模型。
二、GPU 被静默占用
现象:训练刚启动 OOM,但「我没在训啊」。
排查:
1 | nvidia-smi |
常见占显存来源:之前的 llama-server / llama-cli;其他项目的训练容器;没杀干净的 swift 进程。
处理:先停无关容器与进程,再启动训练。后台 stop 脚本要能停到容器内进程,只杀宿主机 PID 往往不够。
三、数据与评测口径
3.1 基座 Exact Match 极低
不一定是「完全不识字」,更常见是:多输出了省份 / 空格 / 解释;标签规范与模型自由生成习惯不一致。LoRA 的价值常常是 对齐格式。
3.2 演示集指标虚高
2k/200 的同分布集合把 Exact Match 打到接近满分,只能证明流水线通,不能证明线上泛化。全量验证与业务抽检不可省略。
四、全量训练运维
4.1 「剩余时间」不可盲信
框架早期估算可能偏乐观;以稳定后的 s/it × 剩余 step 为准。
4.2 中断丢进度
未到 save_steps 就杀进程,多跑的 step 不会进盘。需要频繁中断时,可把 save_steps 调小(代价是磁盘与保存耗时)。
4.3 step 100% 后进程还在
可能在跑最终全量验证或写盘。硬杀可能丢掉最终 checkpoint。看到 train_runtime / 明确完成日志、GPU 释放,再确认结束。
4.4 best ≠ last
验证 loss 最优可能出现在中后段(例如约 2 epoch 附近),最终 step 未必最好。业务上对候选 checkpoint 做同一套评测。
五、合并与导出
5.1 路径混用宿主机 / 容器
容器内必须是 /workspace/...。脚本里最好自动把宿主路径映射过去。
5.2 输出目录互相覆盖
合并产物请带 checkpoint 名;GGUF 文件名写清量化类型。
六、量化
6.1 转换无损 ≠ 量化无损
先确认 F16 GGUF 相对 HF 差不多,再谈 INT4 掉点。否则你会把「转换 bug」误判成「量化损失」。
6.2 模板不一致
同一模型在 HF 与 llama.cpp 两侧要用对齐的 chat template / 提示包装,否则指标不可比。
七、一套「开训前 1 分钟检查」
1 | nvidia-smi # 显存是否空闲 |
八、一句话经验
先小后大,先评后扩,先可续训再长时间跑,先确认转换再谈量化。
多模态微调实战第 09 篇完。下一篇:把全流程命令收进一页速查表。











