指令微调为什么一做 Curriculum Learning 就开始前期收敛快却后期掉泛化:从 Difficulty Bucket 到 Replay Ratio 的工程实战
很多团队给指令微调加上Curriculum Learning后最先看到的是 loss 下降更快、吞吐更平稳评审会上也容易把这当成“训练终于更聪明了”。⚠️ 真正到线上问题却会反着来简单问答更顺复杂推理、长回答和工具约束场景反而更容易漂。图 1课程学习最危险的地方不是前期慢而是前期快得像一切都对了课程学习为什么容易把前期指标优化成假象很多实现只做一件事把短样本、单轮样本和高频模板排在前面。 这样确实能让前1 k - 2 kstep 的梯度更稳定但也会让模型过早适应“短、浅、格式统一”的分布。等难样本后置进入优化器面对的已不是同一条任务曲线而是一次分布切换。更隐蔽的问题在Replay Ratio。 如果课程阶段切换后早期见过的易样本持续出现晚到的难样本占比又不够模型会把 easy pattern 学得越来越硬把真正影响上线质量的长链推理、拒答边界和结构化约束学得越来越晚。表面是 loss 还在降实质是 hard slice 一直没补齐。图 2样本排序改变的不只是学习速度更是模型看到任务边界的先后次序一组 7 B SFT 回放比调学习率更说明问题这次回放的是7 B指令微调任务数据量52万条序列长度8192。 基线组使用全量随机混采方案二采用 easy-first 单向课程方案三改为三段Difficulty Bucket并给 hard bucket 保留18%的 replay floor。结果很直接前期看起来最漂亮的方案终盘并不好。方案前 2 k step 验证 lossHard set 通过率长回答格式通过率典型现象全量随机混采1.9381%88%收敛稳但前期不惊艳easy-first 单向课程1.8472%79%前期快后期 hard slice 回落bucket replay floor1.8885%90%前期略慢终盘最稳这组数据最容易打破的误区是把前期 loss 速度当成课程学习的唯一收益。 easy-first 方案几乎总会更好看因为短样本、固定模板和低冲突回答更容易拟合可一旦上线任务更接近 hard bucket之前省下来的训练噪声会在后期以泛化缺口的形式补回来。最关键的观察不是“课程学习没用”而是它不能只是排序开关。✅ 真正稳的做法是把课程阶段、样本难度和 hard replay 一起建模每个 bucket 单独看 loss、拒答率和格式通过率只要 hard slice 连续两轮不涨就提前抬高 replay而不是继续迷信 easy-first。️defsample_mix(step,total_steps):phasestep/total_steps easy0.55ifphase0.2else0.35medium0.27ifphase0.2else0.37hard0.18ifphase0.2else0.28replaymax(0.18,hard)return{easy:easy,medium:medium,hard:hard,replay_floor:replay}图 3决定最终效果的往往不是最早那段漂亮曲线而是 hard bucket 有没有持续进场生产里要把课程预算做成回放控制生产里更值得默认化的是课程预算而不是课程神话。 难度分桶最好同时看回答长度、工具步数、拒答冲突和人工返修率阶段切换不要按固定 step 硬切而要看 hard bucket 的增益是否真正追上。 如果 hard slice 没有单独记录团队就会一直被总 loss 误导。笔者认为未来3 - 6个月更有效的方向不是更复杂的课程名字而是把Replay Ratio做成训练门禁。 把课程学习从“先喂简单题”升级成“持续控制任务分布”收益才会真正留到上线阶段而不是只留在前几千步的报表里。图 4把课程学习从排队规则升级成分布治理训练收益才会稳定留到上线如果团队现在的课程学习还只是“先喂简单题再喂难题”最该补的不是更细的难度标签而是难样本有没有被持续、可审计地回放进主训练轨迹。你们现在盯的是前2 kstep 的漂亮 loss还是最终 hard slice 的真实通过率