Skip to content

Repository files navigation

tiny-arith-gym 🏋️

用 80 万参数的小模型、40 万条自生成数据、20 组对照实验——完整复现 LLM 训练方法论,并把每一步的收益与代价标定出来。

从 2.2% 到 94.4%(test_id 准确率),不是一次训练的成果,而是 17 组对照实验逐步堆出来的路径。本项目把这个路径完整开源:每个实验都有预注册预测、对照设计、机制解释——包括 **5 次"优雅失败"**的完整记录。

🇬🇧 English documentation: README.en.md


为什么做这个项目

学习 LLM 训练的人面临一个困境:真实大模型训练动辄千卡万卡,看再多文章也无法亲手操作。市面教程又几乎只展示最终成功结果——"哪些方法无效、为什么无效、怎么发现的"恰恰是学习者最缺的内容。

本项目的解法:把任务压缩到一台 Mac 可承载的规模(四则运算表达式计算),但完整保留训练方法论的全貌——数据合成、SFT、架构对照、后训练(RLVR/DPO)、评估方法论,每个环节都有对照实验标定收益。

核心命题:算术的组合空间有限,理论上少量数据就该涌现出真正的运算能力。实际会怎样? 答案比预期复杂得多,见核心发现。

最终成绩

阶段 方法 test_id 准确率 增量
E1 直接输出答案(基线) 2.2% —
E5 化简链 CoT 65.5% +63pp(决定性)
E8a 扩容(805K→4.7M) 70.1% +4.6pp
E8b + RoPE 71.9% +1.8pp
E10 + 数据×3(30 万) 81.8% +9.9pp
E14 + 现实分布采样+交换增强 83.4% +1.6pp
E15 + 反转数字 + 位值嵌入 92.6% +9.2pp
E17 + RLVR (GRPO-lite) 94.4% +1.8pp
— + 推理时 Best-of-N 验证投票 95.5% +1.1pp

从 2.2% 到 95.5%,四十三倍,每一步都有对照实验标定。

核心发现

  1. 化简链 CoT 是唯一决定性杠杆(+63pp)——但粒度有最优值:部分积分解有效(2×2 达 98.6%),拆到逐位(三因子句法)反而崩溃。人类逻辑清晰 ≠ 模型统计顺口。
  2. 反转数字 + 位值嵌入是第二杠杆(+9.2pp)——把进位传播从"跨越数字宽度"变成"相邻位置",自回归生成先出个位、进位顺势传递。3 位数准确率 77.2% → 89.0%。零额外算力,纯表示改进。
  3. 容量与数据是配套插座,单独插哪个都不亮——805K 模型加数据无效(E4),4.7M 模型在 10 万数据上只有 +4.6pp(E8a),两者齐备后 +9.9pp(E10)。
  4. RLVR/GRPO 能压过 SFT 饱和点,但信号受限于组内分歧——全对/全错的组优势为零。复现了 o1/R1 式训练的核心机制与局限。
  5. MoE 专家自发按"数字 vs 运算符"分工(路由概率 0.98)但准确率不变——结构收益 ≠ 准确率收益,可解释性与性能是独立维度。
  6. 两堵未破的墙:长序列组合推理(6+ 操作数 ≈0%,RoPE 无效)与 5 位数以上外推——架构级边界,诚实标注为 future work。
  7. 评估方法论本身就是一门学问——我们踩过并修复了:loss 与准确率脱钩、val-loss 选型埋没最优模型(差 30~50pp)、反转世界验证器的语义错位、评估脚本 bug 制造假结论。见调试编年史。

快速开始

# 1. 环境
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# 2. 生成数据(约 1 分钟,30 万条化简链 CoT)
python src/generate_data.py --cot --n 300000

# 3. 训练(MPS/CPU 约 3.5 小时;tiny 配置见下节约 20 分钟)
python src/train.py --train-file train_cot --cot \
  --block-size 128 --n-embd 256 --n-layer 6 --n-head 8 --steps 60000

# 4. 评估(四测试集 + 按位数分层)
python src/eval_rev.py --ckpt final_best.pt --n 500

tiny 配置(约 20 分钟跑通全流程,适合 first run):

python src/generate_data.py --cot --n 20000
python src/train.py --train-file train_cot --cot --block-size 128 \
  --n-embd 128 --n-layer 4 --n-head 4 --steps 10000

理解实验体系

20 组实验按主题分入 experiments/,每组一个目录:

主题 实验 一句话结论
基线与格式 E01 E02 E03 CoT 化简链 +63pp;错误集中于多位数乘法
数据与采样 E04 E10 E14 数据×容量须配套;现实分布+交换增强 +1.4pp
容量与架构 E08 E15 E16 扩容+4.6pp;反转+位值 +9.2pp;深窄 -3.8pp
后训练 E17 E20 RLVR +1.8pp;DPO +1.4pp(偏好对稀缺)
推理时计算 E18 验证式 BoN 全线 ≥ 贪心,上限=覆盖率
涌现探针 E19 高权重衰减致欠拟合;grokking 未触发
诊断方法论 E07 E09 E13 loss≠准确率;辅助任务有益;MoE 分工涌现

完整原始记录(含全部排障过程): docs/EXPERIMENTS.md

项目结构

├── README.md / README.en.md     # 本文件(中/英)
├── LICENSE                       # MIT
├── requirements.txt
├── src/                          # 最终整合代码
│   ├── tokenizer.py / tokenizer_rev.py   # 字符级 / 位值版(E15)
│   ├── model.py                  # TinyGPT(可开关: RoPE / MoE / ffn_mult)
│   ├── generate_data.py          # 数据合成(多种分布/格式)
│   ├── train.py                  # SFT(含全部实验开关)
│   ├── train_dpo.py / train_grpo.py  # 后训练
│   ├── evaluate.py / eval_rev.py / analyze.py
│   └── ...
├── experiments/                  # E01~E20: 每组实验的文档与复现命令
├── docs/                         # 深入文档
│   └── EXPERIMENTS.md            # 完整原始实验记录
├── data/                         # 数据合成脚本(*.jsonl 产物不入库)
└── scripts/

复现说明

  • 所有训练固定 seed(42),数据生成固定 seed,同类实验共用评估抽样种子
  • 每组实验的精确配置见 experiments/E*/README.md 的复现命令
  • 已知平台注意: Apple MPS 上 (N,64)*(N,) 广播需 unsqueeze(-1)(已在代码内规避)

已知局限(诚实标注)

  • test_len(6+ 操作数长链)≈0%:三种方案(RoPE/更多数据/更多容量)均无效——组合算法缺失,架构级边界
  • 5 位数以上外推 <5%:位值嵌入给了部分脚手架,但容量仍是主限制
  • MoE 在 tiny 尺度无准确率收益(但专家自发按数字/运算符分工,路由概率 0.98,见 E13)
  • grokking 未触发(E19):高权重衰减致欠拟合;正确的 grokking 复现需要小数据+大量 epoch 的不同区间

License

MIT

About

Take an 800K-param GPT from 2.2% to 95.5% on arithmetic through 20 controlled experiments — a hands-on tour of LLM training methods, including the ones that failed.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages