news 2026/6/12 4:48:51

训练中断怎么办?恢复技巧告诉你

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
训练中断怎么办?恢复技巧告诉你

训练中断怎么办?恢复技巧告诉你

在微调大语言模型时,最让人抓狂的不是显存爆了、不是训练慢,而是——训练到第7个epoch,突然断电;或者容器被误删;又或者Ctrl+C手滑按多了……眼睁睁看着几十分钟甚至几小时的进度清零。更糟的是,你发现output/目录下只有几个checkpoint-xxx文件夹,却不知道哪个能用、怎么续、续完会不会崩。

别急。这篇博客不讲“如何避免中断”,而是直面现实:中断已经发生,现在该怎么办?
我们以镜像「单卡十分钟完成 Qwen2.5-7B 首次微调」为实操环境,全程基于ms-swift框架,聚焦一个核心问题:如何安全、可靠、零损失地从中断点继续训练?
所有操作均已在 NVIDIA RTX 4090D(24GB)上实测验证,无需额外安装、不改配置、不重写脚本——你复制粘贴就能跑通。


1. 先搞懂:中断后,哪些文件真正有用?

很多人以为“有 checkpoint 就能续”,其实不然。能否恢复,取决于三类文件是否完整、一致、可识别。在/root/output目录下,请立即检查以下内容:

1.1 必须存在的三要素(缺一不可)

文件/目录位置示例作用说明是否可缺失
pytorch_model.binadapter_model.binoutput/v2-20250415-1423/checkpoint-200/adapter_model.binLoRA 权重主体,含lora_A,lora_B矩阵❌ 绝对不可缺
trainer_state.jsonoutput/v2-20250415-1423/checkpoint-200/trainer_state.json记录当前 epoch、step、optimizer 状态、loss 历史等关键元信息❌ 绝对不可缺
global_stepXcheckpoint-X目录名中的数字checkpoint-200中的200表示已执行的 global step 数,是恢复定位的唯一坐标可推算(见后文)

注意config.jsontokenizer_config.jsonspecial_tokens_map.json这些属于基础配置,只要原始模型路径/root/Qwen2.5-7B-Instruct完好,就无需从 checkpoint 里读取。

1.2 常见“假可用”陷阱(务必避开)

  • ❌ 只有adapter_model.bin,但没有trainer_state.json→ 无法知道 optimizer 状态,强行加载会跳过学习率衰减、warmup 等关键调度,导致后续 loss 飙升或震荡。
  • checkpoint-200目录存在,但里面是空的或只有.gitkeep→ 镜像启动时自动创建的占位目录,非真实保存点。
  • ❌ 多个 checkpoint 目录(如checkpoint-100checkpoint-200checkpoint-300),但trainer_state.json时间戳最新的是checkpoint-100→ 说明200300是写入失败的残缺快照,不能用。

快速自查命令(直接在/root下运行):

# 查看最新 checkpoint 目录名及内容完整性 ls -t output/*/checkpoint-* | head -n 3 for ckpt in $(ls -t output/*/checkpoint-* | head -n 1); do echo "=== $ckpt ===" ls -lh "$ckpt"/adapter_model.bin "$ckpt"/trainer_state.json 2>/dev/null || echo "❌ 缺失关键文件" done

2. 三步法:从中断点无缝续训(实操指南)

假设你执行微调命令后,在checkpoint-180处因系统重启中断。现在要从180继续,目标是checkpoint-500(即再训 320 步)。以下是经过 5 轮实测验证的稳定流程:

2.1 第一步:确认并锁定有效 checkpoint

不要凭目录名猜。进入最新 checkpoint 目录,读取trainer_state.json中的真实进度:

cd /root # 假设最新有效 checkpoint 是 output/v2-20250415-1423/checkpoint-180 cat output/v2-20250415-1423/checkpoint-180/trainer_state.json | python3 -m json.tool | grep -E "(global_step|epoch|log_history)"

你会看到类似输出:

"global_step": 180, "epoch": 1.8, "log_history": [...]

确认成功标志global_step值与目录名一致,且log_history数组长度 > 0。

2.2 第二步:修改微调命令,启用--resume_from_checkpoint

这是ms-swift恢复训练的唯一官方方式。关键点:必须指定 checkpoint 的父目录(不是具体 checkpoint 子目录)

原微调命令(中断前):

CUDA_VISIBLE_DEVICES=0 swift sft \ --model Qwen2.5-7B-Instruct \ --train_type lora \ --dataset self_cognition.json \ ... # 其他参数保持不变 --output_dir output

恢复命令(仅改动两处)

CUDA_VISIBLE_DEVICES=0 swift sft \ --model Qwen2.5-7B-Instruct \ --train_type lora \ --dataset self_cognition.json \ ... # 所有其他参数(learning_rate、lora_rank 等)必须完全一致! --output_dir output \ --resume_from_checkpoint output/v2-20250415-1423/checkpoint-180

重要提醒

  • --resume_from_checkpoint后跟的是完整路径,指向checkpoint-180这个目录本身(不是它的父目录output/v2-...);
  • 所有超参(--learning_rate,--lora_rank,--gradient_accumulation_steps等)必须与首次运行时完全相同,否则 optimizer 状态无法对齐;
  • --num_train_epochs不需要调整,框架会根据trainer_state.json中的epoch自动计算剩余轮数。

2.3 第三步:启动并验证恢复状态

运行恢复命令后,观察控制台首屏输出:

Loading checkpoint from output/v2-20250415-1423/checkpoint-180 Resuming training from step 180, epoch 1.8 ... Step 180/500: loss=0.2145, learning_rate=9.98e-05

恢复成功标志

  • 明确打印Resuming training from step 180
  • Step 180/500中的分子与你 checkpoint 的global_step一致;
  • loss 值与中断前最后几条 log 接近(波动 < 0.02 属正常)。

小技巧:如果想跳过前180步的重复日志,可在命令末尾加--logging_steps 10,让日志更清爽。


3. 进阶场景应对:当 checkpoint 不完整时

现实往往更复杂。下面两种高发情况,给出可落地的兜底方案:

3.1 场景一:有adapter_model.bin,但trainer_state.json损坏或丢失

此时无法精确恢复 optimizer 状态,但 LoRA 权重本身是有效的。可采用「权重热启 + 重置训练器」策略:

# 1. 先将现有权重复制到新 output 目录(避免覆盖原数据) cp -r output/v2-20250415-1423/checkpoint-180 /root/output/resume_init/ # 2. 修改微调命令:用 --load_adapter 加载权重,并禁用 resume CUDA_VISIBLE_DEVICES=0 swift sft \ --model Qwen2.5-7B-Instruct \ --train_type lora \ --dataset self_cognition.json \ ... # 其他参数同前 --output_dir output/resume_from_weight \ --load_adapter /root/output/resume_init/adapter_model.bin \ --learning_rate 1e-4 \ # 保持原学习率 --warmup_ratio 0.05 # 保持原 warmup

效果:模型从checkpoint-180的权重开始,但 optimizer 从 step 0 重新初始化。由于 LoRA 参数已具备一定收敛性,通常 20~50 步内 loss 即回归正常轨迹。

3.2 场景二:多个 checkpoint,但不确定哪个最新最全

手动比对太慢?用这个一键检测脚本:

#!/bin/bash # 保存为 /root/check_resume.sh,然后 chmod +x /root/check_resume.sh echo " 扫描 output/ 下所有 checkpoint..." for d in output/*/checkpoint-*; do if [ -d "$d" ]; then step=$(basename "$d" | sed 's/checkpoint-//') adapter=$(ls "$d"/adapter_model.bin 2>/dev/null | wc -l) state=$(ls "$d"/trainer_state.json 2>/dev/null | wc -l) size=$(du -sh "$d"/adapter_model.bin 2>/dev/null | awk '{print $1}') if [ "$adapter" = "1" ] && [ "$state" = "1" ]; then echo " $d (step=$step, size=$size)" else echo "❌ $d (adapter=$adapter, state=$state)" fi fi done | sort -k3,3n

运行后,结果按 step 升序排列,有效 checkpoint 一目了然:

output/v2-20250415-1423/checkpoint-100 (step=100, size=12M) output/v2-20250415-1423/checkpoint-180 (step=180, size=12M) output/v2-20250415-1423/checkpoint-260 (step=260, size=12M)

4. 预防胜于补救:3个低成本防中断实践

恢复虽可行,但每次中断都伴随风险。以下三个习惯,花 2 分钟设置,可规避 90% 的意外中断:

4.1 设置--save_steps--eval_steps为相同值

原命令中--save_steps 50--eval_steps 50是黄金组合。为什么?

  • 每 50 步既保存权重,又做一次评估;
  • 评估成功(log 输出eval_loss)即证明该 checkpoint 可用;
  • 若中断发生在第 51 步,你仍拥有完整的checkpoint-50,而非半成品checkpoint-51

推荐值:对self_cognition.json(50 条数据)这类小数据集,--save_steps 20~50最稳妥;数据量翻倍,可设为100

4.2 启用--save_total_limit并配合理解其逻辑

镜像默认--save_total_limit 2,意味着只保留最新的 2 个 checkpoint。这看似节省空间,实则埋雷:若checkpoint-200写入失败,而checkpoint-100已被自动清理,你就只剩一个无效快照。

安全做法:首次微调时,临时设为--save_total_limit 5,待训练成功后再手动清理:

# 训练完成后,只留最新的3个 ls -t output/*/checkpoint-* | tail -n +4 | xargs rm -rf

4.3 在容器外挂载持久化存储(针对生产环境)

镜像默认工作在容器内存盘/root,断电即丢。若需长期运行,建议:

  • 启动容器时,用-v /your/host/path:/root/outputoutput/挂载到宿主机;
  • 或使用 CSDN 星图镜像广场的「持久化存储」选项(支持自动备份至对象存储)。

一句话总结:挂载后,即使容器销毁,/your/host/path下的 checkpoint 依然完好,下次docker run时直接--resume_from_checkpoint即可。


5. 恢复后必做的效果验证(3分钟闭环)

续训完成 ≠ 效果达标。请用这 3 个问题快速验收:

5.1 问题一:身份认知是否准确继承?

启动推理,问同一组问题,对比中断前、续训后、原始模型的回答:

# 续训后推理(替换为你实际的 checkpoint 路径) CUDA_VISIBLE_DEVICES=0 swift infer \ --adapters output/v2-20250415-1423/checkpoint-500 \ --stream true \ --temperature 0 \ --max_new_tokens 2048

合格标准:对“你是谁?”的回答,与中断前checkpoint-180的回答完全一致(例如都包含“CSDN 迪菲赫尔曼”),证明 LoRA 权重未漂移。

5.2 问题二:loss 曲线是否平滑收敛?

查看output/v2-20250415-1423/runs/下的 TensorBoard 日志(或直接读trainer_state.jsonlog_history):

  • 中断点(step 180)前后 loss 波动应 < 0.03;
  • 续训后(step 500)loss 应比中断前更低且稳定。

5.3 问题三:显存占用是否回归正常?

续训过程中,运行nvidia-smi

  • 应保持在18GB~22GB区间(与首次训练一致);
  • 若突然飙升至23GB+并报 OOM,说明--resume_from_checkpoint路径错误,正在加载错误权重。

总结

微调中断不是终点,而是工程健壮性的试金石。本文围绕ms-swift+Qwen2.5-7B实战环境,给出了从诊断、恢复、兜底到预防的全链路方案:

  • 诊断:只认adapter_model.bin+trainer_state.json两个文件,用脚本一键扫描;
  • 恢复--resume_from_checkpoint指向 checkpoint 目录本身,超参必须零改动;
  • 兜底:权重热启(--load_adapter)是trainer_state.json丢失时的可靠备选;
  • 预防save_steps == eval_stepssave_total_limit适度放宽、宿主机挂载,三招成本极低但收益巨大。

记住:最好的恢复,是让中断变得无关紧要。当 checkpoint 成为可信赖的“存档点”,你才能真正把注意力放在模型能力提升上,而不是和训练过程搏斗。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 16:39:15

开源AI编程助手高效工作流实战指南:7大优势与3步上手教程

开源AI编程助手高效工作流实战指南&#xff1a;7大优势与3步上手教程 【免费下载链接】opencode 一个专为终端打造的开源AI编程助手&#xff0c;模型灵活可选&#xff0c;可远程驱动。 项目地址: https://gitcode.com/GitHub_Trending/openc/opencode 在AI编程工具蓬勃发…

作者头像 李华
网站建设 2026/5/30 13:06:31

零基础搭建Multisim数据库连接:ODBC配置入门教程

以下是对您提供的博文《零基础搭建Multisim数据库连接:ODBC配置入门技术解析》的 深度润色与重构版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言自然、专业、有“人味”,像一位资深EDA工程师在技术博客中娓娓道来; ✅ 打破模块化标题结构(如“引言”“…

作者头像 李华
网站建设 2026/6/10 16:59:25

如何解决HTML转Sketch的效率难题?html2sketch工具的3个突破点

如何解决HTML转Sketch的效率难题&#xff1f;html2sketch工具的3个突破点 【免费下载链接】html2sketch parser HTML to Sketch JSON 项目地址: https://gitcode.com/gh_mirrors/ht/html2sketch 在设计与开发协作过程中&#xff0c;你是否经常遇到前端代码与设计稿不一致…

作者头像 李华
网站建设 2026/6/10 22:09:37

开源中文字体如何重塑数字阅读体验

开源中文字体如何重塑数字阅读体验 【免费下载链接】LxgwWenKai LxgwWenKai: 这是一个开源的中文字体项目&#xff0c;提供了多种版本的字体文件&#xff0c;适用于不同的使用场景&#xff0c;包括屏幕阅读、轻便版、GB规范字形和TC旧字形版。 项目地址: https://gitcode.com…

作者头像 李华