llamafactory sft微调坑 继续训练 ,为什么 `save_steps: 40` 没有生效,实际 100 步才保存
llamafactory sft微调坑 继续训练 ,为什么save_steps: 40没有生效,实际 100 步才保存
这是一个很典型的问题,让我帮你排查。核心怀疑是:从 checkpoint 恢复训练时,save_steps被旧 checkpoint 里的training_args覆盖了。
让我先检查一下你的 checkpoint 目录和配置文件:
Sandbox 里没有你的实际文件,让我写一个你可以在本机运行的诊断脚本,同时先给你分析最可能的原因:
分析:为什么save_steps: 40没有生效,实际 100 步才保存?
你的配置看起来没问题,save_steps: 40写得很清楚。问题最可能出在resume_from_checkpoint上。以下是排查思路:
🔴 最可能的原因:旧 checkpoint 里的training_args覆盖了新配置
你的checkpoint-600很可能是之前用save_steps: 100训练保存的(600 ÷ 100 = 6,恰好整除)。
当使用resume_from_checkpoint时,HuggingFace Trainer / LLaMA-Factory 可能会从 checkpoint 目录下的training_args.json读取旧的训练参数(包括save_steps: 100),覆盖你新配置的40。
验证方法:在你本机运行上面的诊断脚本,重点看第 3 步的输出:
checkpoint-600/training_args.json 里的 save_steps 是多少?- 如果是100→ 确认是旧配置覆盖了
- 如果是40→ 需要看其他原因
🟡 其他可能原因
| # | 可能原因 | 说明 |
|---|---|---|
| 1 | 命令行参数覆盖 | 如果启动时用了--save_steps 100命令行参数,会覆盖 YAML 配置文件 |
| 2 | LLaMA-Factory 版本行为 | 某些版本的 LLaMA-Factory 在 resume 时会从 checkpoint 恢复完整的 TrainingArguments |
| 3 | save_strategy未显式设置 | 虽然 HF 默认save_steps设了就自动用"steps",但某些版本需要显式指定 |
✅ 解决方案(按推荐顺序)
方案 1:删除旧 checkpoint 中的training_args文件(推荐)
# 删除旧的 training_args,强制使用新配置rm/mnt/workspace/output/train_1024_0/checkpoint-600/training_args.jsonrm/mnt/workspace/output/train_1024_0/checkpoint-600/training_args.bin2>/dev/null# 但保留 trainer_state.json(里面保存了 global_step 等恢复信息)然后重新启动训练,新配置的save_steps: 40应该会生效。
方案 2:显式添加save_strategy
在 YAML 配置中加上:
save_strategy:stepssave_steps:40方案 3:检查启动命令
确认启动命令中没有通过命令行覆盖:
# ❌ 如果有这样的命令行参数,会覆盖 YAML--save_steps100# ✅ 确保只通过 YAML 文件配置llamafactory-cli train your_config.yaml方案 4:如果以上都不行 — 手动修改 checkpoint 的 step 计数
importjson# 修改 trainer_state.json,让 global_step 对齐到 40 的倍数path="/mnt/workspace/output/train_1024_0/checkpoint-600/trainer_state.json"withopen(path)asf:state=json.load(f)# 600 已经是 40 的倍数 (600/40=15),所以这里不需要改# 但确认 save_steps 字段state['save_steps']=40# 强制写入withopen(path,'w')asf:json.dump(state,f,indent=2)print("已修改 trainer_state.json 中的 save_steps 为 40")📋 快速诊断清单
请在你的机器上运行以下命令,把结果发给我:
# 1. 看旧 checkpoint 的训练参数cat/mnt/workspace/output/train_1024_0/checkpoint-600/trainer_state.json|python-mjson.tool|grep-E"save_steps|global_step|logging_steps"# 2. 看 training_args.jsoncat/mnt/workspace/output/train_1024_0/checkpoint-600/training_args.json|python-mjson.tool|grep-E"save_steps|logging_steps|eval_steps"# 3. 看启动命令(检查是否有命令行覆盖)# 确认你的启动方式,是否额外传了 --save_steps 参数最关键的一步:看checkpoint-600/training_state.json里的save_steps值。如果它是 100,那就是罪魁祸首——修改这个文件再重启训练即可。
直接删除training_state.json可能会报错,导致训练无法启动。因为 HuggingFace Trainer 或 LLaMA-Factory 在恢复训练时,可能会尝试读取这个文件;如果找不到,可能会抛出FileNotFoundError。
更安全、更推荐的做法是:直接修改里面的值,而不是删除。
我们可以直接把旧 checkpoint 里的save_steps强制改成 40,这样既不影响恢复训练(优化器状态、步数等依然保留),又能让新配置生效。
你可以直接在终端运行这段 Python 脚本来“安全打补丁”:
importjsonimportos ckpt_dir="/mnt/workspace/output/train_1024_0/checkpoint-600"# 1. 修改 training_state.jsonta_path=os.path.join(ckpt_dir,"training_state.json")ifos.path.exists(ta_path):withopen(ta_path,'r')asf:ta=json.load(f)ta['save_steps']=40ta['logging_steps']=20# 顺便确保日志也是你要的频率withopen(ta_path,'w')asf:json.dump(ta,f,indent=2)print(f"✅ 已修改{ta_path}中的 save_steps 为 40")# 2. 修改 trainer_state.json (HuggingFace 的状态文件里也会存一份)ts_path=os.path.join(ckpt_dir,"trainer_state.json")ifos.path.exists(ts_path):withopen(ts_path,'r')asf:ts=json.load(f)ts['save_steps']=40ts['logging_steps']=20withopen(ts_path,'w')asf:json.dump(ts,f,indent=2)print(f"✅ 已修改{ts_path}中的 save_steps 为 40")总结一下哪些文件能动,哪些不能动:
在checkpoint-600文件夹里:
- ❌绝不能删:
adapter_model.bin或pytorch_model.bin(模型权重)、optimizer.bin(优化器状态)、scheduler.pt(学习率调度器)、rng_state.pth(随机数种子)。删了等于没法接着训练了。 - ⚠️不要直接删,建议修改:
training_state.json、trainer_state.json。删了可能报错,按上面的脚本改成你想要的数值最稳妥。 - ✅可以删:
training_state.bin(如果存在的话,这是旧版遗留文件,一般没用)。
你先跑一下这个脚本打补丁,然后再用原本的 YAML 配置启动训练,这次 40 步应该就会乖乖保存了!
