从 135M 试跑到 Qwen3-1.7B:训练过程
任务与角色
用户提供 verl-recipe 的 char_count 任务,并要求跳过 SFT、直接做 GRPO。每题询问某个字符在合成字符串中出现几次,例如 How many a are there in word a-b-a?。参考答案为计数;字符串由小写字母随机生成,字符间带连字符,并非自然语言单词。
Naive 通过 Claude Code 编写/调整启动配置、运行命令、查看指标、维护定时巡检和后台监听。用户决定任务方向,后来建议 Qwen3-1.7B,并选择跑 2 epochs。不能将这个过程描述成完全没有人工参与的自主研究,也不能把 Naive 写成被训练模型。
实际发生的顺序(UTC)
| 时间/阶段 | 动作或观测 |
|---|---|
| 15:52 起 | 引入 char_count recipe,明确不做 SFT;当时已有数学实验,暂缓切换 |
| 16:34 后 | 开始切换任务,准备模型、数据和容错 reward |
| 16:48 左右 | SmolLM2-135M-Instruct 开始直接 GRPO;验证基线约 2.6% |
| 17:01 | 135M 提升有限,助手提出调高学习率等建议;建议不能算已实施变更 |
| 17:10–17:13 | 用户建议换为 Qwen3-1.7B 并选择 2 epochs;关闭 thinking,保留 lr=1e-6 |
| 17:14:01 | Qwen3-1.7B 轮次容器启动,实际训练 140 步 |
| 17:16 | 训练前基线 21.3%;旧 watcher 错把基线超过阈值当成“爬坡”,修为 step>0 且 val≥0.30 |
| s70 | 验证准确率 45.2% |
| s75 → s80 | 47.4% → 46.2%;助手过早判断已达到 128-token 上限造成的平台 |
| s100 | 51.5%;推翻“已经收敛/天花板已到”的判断 |
| s140,约 19:05 | 最终验证准确率 54.4%,训练进度条完成 140/140 |
最终成功轮次启动后没有新增人工训练指令,也没有执行中途训练参数调整。7 次定时巡检在 17:21、17:36、17:51、18:06、18:21、18:36、18:51 左右发生。后台监听、阶段报告和收尾不计入这 7 次。
这里只统计最终成功轮次;更早的任务选择、数学实验和 135M 试跑包含额外人工指令。
结果与判分口径
保存的数据为 9000 条训练、1000 条验证;140 个训练点,含 s0 在内共 29 个验证点。指标来自最终 Qwen worker 的日志,提取时用 TaskRunnerV1 pid=2351 与 step 字段隔离,避免混入前面的 135M 数据。完整数值见 results/metrics.csv,可由脚本从脱敏日志重建。
- 验证准确率从 0.213 到 0.544,增加 33.1 个百分点。
- response 长度触顶比例从 s1 的 0.92285 到 s140 的 0.40820。这里的 clip_ratio 是长度指标,不是 PPO 的
pg_clipfrac。 - s140 的训练 reward 为 0.50098;它是一个训练 batch 的均值,不是验证准确率。
- 训练进度条用时 1:49:50;从容器启动算约 1h51m,二者统计边界不同。
训练使用已有的 GSM8K 容错判分函数,接受 ####、\\boxed{},并可回退到末尾数字。优先级为严格 #### → 含 #### 的同一行数字 → boxed → 尾部最后数字。这个设置使格式不合规的正确计数可能获奖,也会使无关数字恰好命中标签。发布代码保留这项行为,以便复现历史结果。
不能将此次准确率等同于严格 boxed 判分,不能据此声称超过官方 SFT+GRPO recipe,也不能证明多次运行都会达到 54.4%。验证集在训练中被反复观测,不是独立盲测。按完整 prompt 比对,训练/验证存在 62 个相同的唯一问题;数据生成器未强制去重,本次保留原数据并公开这个限制。
保留误判,区分观测与解释
- 基线触发了旧 watcher。“监控报警”本身不是训练提升证据,需同时检查 step 和相对基线增益。
- s80 回落后,助手曾把短平台解释为 128-token 的结构性天花板。后续在同样上限下继续提升,说明这个强结论不成立。
- 长度触顶率与准确率同时改善,是相关观测;没有对照实验,不能断言前者就是后者的唯一原因。
- 换模同时改变了模型、thinking 开关和训练轮数,不是严格的单变量对照。
- 旧对话中包含预测时长、预测终点和“零事故”等当时判断。公开摘录保留原话,但最终报告以可核对记录为准。
收尾异常与保留范围
日志在 140/140 完成附近含 RuntimeError: DataLoader worker ... is killed by signal: Killed 和 worker 退出信息;同一日志也记录了 step 140 与最终验证 0.544。可确认的是训练步与最终评测结果已写出,不能仅凭这些日志宣称所有进程都正常退出,也无法断定该 kill 的具体原因。
随后用户要求清理训练资源,历史 checkpoint、optimizer/offload 状态、训练专用模型下载及容器/镜像已删除。保留下来的代码、数据和日志构成本仓库;无法从已删除的权重继续训练或重新评估最终模型。