Files
xtrain/docs/runs/05-v5-tinystories-dim768.md
Gahow Wang 579365f4a0 docs: run v5 — TinyStories saturation at dim768 (val 1.11)
设计文档 05-v5-tinystories-dim768.md(中文,xserv 风格):数据 2.49B tok/5.33ep、
架构同 v4(净测数据变量)、bf16 8 卡 global 256、train 11.07→1.06 best val 1.1102。
核心发现「数据天花板」:v4(1.54ep)1.169→v5(5.33ep)1.110 仅 ↓5% 且末段 val 走平
⇒ TinyStories 在 dim768/127M-core 近饱和,v6 该换轴(更大模型/更广语料,非更多 TinyStories)。
xserv BF16 服务 3/3 prompt 逐 token 一致。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:56:25 +08:00

14 KiB
Raw Blame History

Scaling Run v5: TinyStories 多遍(5.33 ep) + dim768/18L(同 v4) + 8 卡 DDP bf16 — Design Document

Goal

v4 把模型放大到 dim768/18Lcore 127.43M),训了 ~720.9M token~1.54 epochval 一路降到末步仍在降 = 仍欠拟合。当时留下一个明确问题:TinyStories 这本语料对 127M core 模型,到底是不是数据上限?

v5 是为回答这个问题专门设计的对照实验

  1. 架构完全冻结 = v4dim 768 / 24 heads × 32 head_dim / 18 layers / SwiGLU ffn 2048core 127.43M 总 204.63M)。一个权重维度都不改——这样 v4→v5 的 val 差异只能归因于「更多数据」这一个变量
  2. 数据放大到接近饱和v5 训 ~2.49B token = ~5.33 epochv4 才 1.54 ep同一份全量 TinyStories token 流多跑 3.5×,看 val 还能不能继续降。
  3. bf16T12/KI-2找回甜点区v4 是 bf16 的触发点——dim768 fp32 在 32GB 显存里 per-rank batch 32 global 256OOM被迫降到 per-rank 16global 128。v5 上 bf16 混合精度fp32 master激活减半 → 找回 per-rank 32 / global 256 的甜点区,同时吞吐从 v4 的 ~145K 升到 ~217K tok/s。
  4. 训完存 registry + 导出 xserv 验证可服务,给出相比 v4 的提升数据天花板结论

这一版的工程意义v5 是 xtrain scaling 阶梯上第一个有意不放大模型的版本——它不是为了「更低的 val」 而是为了测准 TinyStories 在 dim768 的数据天花板。结论(见下)很干脆:3.5× 数据只换来 ~5% 的 val 改善,且末段 val 走平——同尺寸模型在 TinyStories 上已近饱和v6 该换轴(更大模型 / 更广语料),而不是 继续榨 TinyStories 的 epoch。同时 v5 兑现了 v4 留的 bf16 杠杆KI-2bf16 找回 global 256 甜点区, 8 卡稳态 ~217K tok/s。

数据

v4 v5
来源 TinyStories 全量 train(复用 v1 缓存)
token 数(语料) 468,260,367
训练消费 token ~720.9M22000 步 × 32768 ~2.49B38000 步 × 65536
epoch 占比 ~1.54 ~5.33×3.5
tokenizer gpt2 BPEvocab 50257
缓存 data/tinystories-train.txt.u16.binu16 直接复用
held-out val 全量末尾 1,000,000 token 同一 1M token(与 v0v4 完全相同的保留集,公平对比)

复用缓存Corpus::load_cached<corpus>.u16.bin,启动即载入 467.26M train token末尾 1M 留 val。 held-out val 仍是全量末尾 1M tokensplit_tail),与 v0v4 同一保留集——v0v5 的 val loss 直接可比

这一版数据设计的核心v4 才 1.54 epochv5 把同一份语料喂到 5.33 epoch×3.5)。如果 TinyStories 对 127M core 还有数据空间val 该继续显著下降如果已近饱和val 会迅速放缓、走平。v5 就是来读这个信号的。

架构

v5 = 与 v4 字节级同构的 tiny Qwen3RoPE + RMSNorm + per-head QK-norm + SwiGLU + 独立 lm_headMHA刻意一个维度都不改,让「更多数据」成为唯一被测变量。

维度 v4 v5
dim= heads·head_dim 768 768
n_layers 18 18
n_heads 24 24
head_dim 32 32
ffn_hiddenSwiGLU 2048 2048
vocab 50257 50257
core 参数 127,432,704≈127.43M 127,432,704
embed + lm_head2×vocab×dim 77,194,752≈77.19M 77,194,752
总参数 204,627,456≈204.63M 204,627,456

为什么不放大模型scaling 实验里「数据」和「容量」两个变量若同时动val 的变化无法归因。v4→v5 把容量冻死、 只动数据,得到的 val 差就纯粹是数据的边际收益——这是判断「TinyStories 是否到数据天花板」的唯一干净办法。 config.json 与 v4 完全一致(导出的 201 tensors 形状一字不差)。

训练器8 卡 DDP bf16T12 混合精度fp32 master

v4 用 8 卡 DDP fp32,被 dim768 的显存压到 per-rank batch 16global 128。v5 切 bf16 混合精度

  • fp32 master 权重 + AdamW/clip/DDP 全部保持 fp32(数值安全),只把 linears 走 cublasGemmEx16BF 输入 / fp32 accum、激活存 bf16norm/softmax/rope/CE 仍 fp32。新增 cast autodiff op 桥接fwd 降精度 / bwd 升精度)→ 优化器零改动。无 loss scalingT12 实测 dim768 不需要)。
  • 激活减半 → 找回甜点区bf16 把 dim768 的 per-rank batch 重新撑到 32global 256,正是 v4 因 fp32 OOM 失去的甜点区。同时吞吐 ~145Kv4 fp32→ ~217K tok/sv5 bf16×1.5
  • 8 卡 thread-per-GPUall-reduce device 梯度取均值后各 rank 本地 GpuAdamW step跨 rank 参数 bit-identical T8/T11 已验证)。

全程稳态 ~217,000 tok/s、wall-clock ~3.2h 训完 2.49B token。bf16 收敛全程对住 fp32T12 已做 150 步 3.984 vs 3.988 对拍v5 的 train/val 曲线平滑无异常。

超参

备注
optimizer 手写 AdamWGPU 端 step wd=0.1,β/eps 用 xtrain-optim 默认
LR schedule 线性 warmup → cosine decay max_lr 6e-4 → min_lr 6e-5(同 v1v4
warmup ~1900 步lr 在 ~step 1900 达峰 6.00e-4cosine 衰减到末步 6e-5
grad clip global-norm 1.0 gnorm 全程平稳warmup 后 ~0.4 起持续下降)
steps 38000 ~3.2h @ 8 卡
global batch 256per-rank 32 × world 8 bf16 找回的甜点区v4 fp32 只能 128
seq_len 256 同 v2v4
tokens/step 256×256 = 65536 总训练 token ≈ 2.49B~5.33 epoch
world size 8RTX 5090sm_120
精度 bf16 混合精度fp32 master T12/KI-2导出 xserv 同样 BF16

算力dash5 8× RTX 5090全程 ~217,000 tok/sstep 50 起即稳态wall-clock ≈ 3.2 小时

结果

  • train lossstart 11.0675 → end 1.0588(全程平滑下降)
  • best val lossheld-out 1M tokenstep 349991.1102
  • final val lossstep 379991.1131
  • val loss 曲线(每 ~2000 步抽样):
step 499 1999 3999 5999 7999 9999 13999 17999 21999 25999 29999 33999 34999 37999
val 2.6838 1.6033 1.4132 1.3317 1.2980 1.2596 1.2194 1.1846 1.1575 1.1374 1.1217 1.1151 1.1102 1.1131

⚠️ 数据天花板:末段走平

v5 的 val 在末段明显走平——这是 v4 单调下降曲线上看不到的新行为:

step 34999 35499 35999 36499 36999 37499 37999
val 1.1102 (best) 1.1126 1.1131 1.1135 1.1119 1.1143 1.1131

best1.1102)出现在 step 34999之后 3000 步 val 在 1.11021.1143 的 ~0.004 带内来回抖动、不再单调下降。 对比 v4 的 val 一路降到末步仍在降(欠拟合)——v5 已经把 TinyStories 这本语料学到平台期

相比 v4 的提升 —— 以及数据天花板分析

完整 val 阶梯(各版各自 best val同一 1M token 保留集)

模型 core 参数 训练 token epoch best val 相比上一版
v0-baseline 41K ~0.72M 3.8050
v1 8.39M ~5.1M 2.5847 ↓1.22
v2 28.32M ~36.9M 1.7055 ↓0.88
v3 67.13M ~245.8M ~0.53 1.3027 ↓0.40
v4 127.43M ~720.9M ~1.54 1.1690 ↓0.13
v5 127.43M(同 v4 ~2.49B×3.5 ~5.33 1.1102 ↓0.06(仅 ~5%

这是本版的核心发现。把它和前几档对比v2→v3 数据 ×6.7val ↓0.40v3→v4 数据 ×2.9 + 模型 ×1.9 val ↓0.13)。而 v4→v5模型不变、数据 ×3.5val 只 ↓0.06~5%。结合末段走平:

结论:在 dim768 / 127M-core 这个尺寸TinyStories 已接近数据饱和。 同一份语料从 1.54 epoch 喂到 5.33 epoch×3.5val 仅改善 ~5% 且末段走平——「更多 TinyStories token」 这条杠杆已经基本榨干。这不是模型欠拟合v4 那种末步仍降),而是语料的信息量对这个尺寸的模型已学尽

下一档v6的杠杆按收益排序

  1. 换轴:更大模型 或 更广语料——这两条才是 v5 之后真正能继续降 val 的方向。
  2. 不该做:继续加 TinyStories 的 epoch。v5 已经证明 6+ epoch 的边际收益薄到不值得算力。

并排采样greedy 40 tokxserv 服务,同 promptv4 vs v5

prompt v4 v5
Once upon a time …a little girl named Lily. She loved to play outside in the sunshine. One day, she saw a big, scary dog. She was scared and ran away. …a little girl named Lily. She loved to play outside in the park. One day, she saw a big, white cloud in the sky. It looked like a fluffy pillow.
One day One day, a little girl named Lily went to the park with her mom. She saw a big tree with a swing. Lily wanted to play on the swing, but she was too small. She asked her One day, a little girl named Lily went to the park with her mom. She saw a big tree with a swing. Lily wanted to play on the swing, but she was too small to reach it.
The little The little girl was so happy that she had found the perfect place to hide. She stayed there for a long time, until it was time to go home. She said goodbye to the tree The little girl was so happy that she had found the perfect thing to replace the broken one. She thanked her mom and they both went home with a smile on their faces.

结论v4 和 v5 都写出完整、连贯、有收束的 TinyStories——两者质量在同一水平,差异是情节走向的细微不同 "scary dog → ran away" vs "white cloud → fluffy pillow"而非可感知的质量提升。这与 val 仅 ↓0.06 完全一致: 同尺寸模型多看 3.5× 数据,采样质量已无肉眼可见的提升——这是数据天花板在生成侧的直接体现。

xserv 验证

导出 HF Qwen3 safetensors命名映射 + 2D 权重转置 [in,out]→[out,in] + BF16见 T9 docs/08 201 tensors = 18 层 × 11 + embed + norm + lm_headconfig.json 与 v4 一字不差),存入 registry 后用 xserv-cli 加载并贪心生成:

$ xserv-cli ~/projects/tiny-models/v5-tinystories-dim768 --max-tokens 40
Model: qwen3, layers=18, hidden=768, heads=24/24 kv, vocab=50257
Loaded 201 tensors
xserv> Once upon a time, there was a little girl named Lily. She loved to play outside in the park.
       One day, she saw a big, white cloud in the sky. It looked like a fluffy pillow.
xserv> One day, a little girl named Lily went to the park with her mom. She saw a big tree with a
       swing. Lily wanted to play on the swing, but she was too small to reach it.
xserv> The little girl was so happy that she had found the perfect thing to replace the broken one.
       She thanked her mom and they both went home with a smile on their faces.

token-matchxservBF16对 xtrain 自身贪心,3 个 prompt 全部逐 token 完全一致40 tok 内零分叉)。 v5 训练即 bf16fp32 master权重本就在 bf16 数值域里收敛,导出 BF16 给 xserv 后两侧贪心匹配更紧v4 是 fp32 训练 → BF16 导出,已 3/3 一致v5 同样 3/3 且数值路径更一致)。闭环成立。

v6 提案

v5 给出了明确的数据天花板结论v6 该换轴。两条候选:

  • A. 更大模型dim 1024+v5 证明 TinyStories 对 127M core 已饱和,但更大的模型也许能从同一语料里 榨出更多(容量上限尚未触顶)。注意 dim 越大embed/lm_head 占比越摊薄dim768 时 77.19M / 204.63M ≈ 38% dim1024 会降到 ~34%)→ KI-4大词表占比的压力反而变小。但若只换更大模型、仍喂 TinyStories很可能 很快又撞上「这本语料的信息上限」——TinyStories 本身的内容多样性有限。
  • B. 更广语料FineWeb-edu 等通用高质语料)+ 可能换 tokenizerKI-4v5 的天花板是语料的天花板, 不是模型的。换更丰富的语料能抬高数据本身的信息量上限,让更大的模型有东西可学。配合换更小/更贴合的 tokenizerKI-4可进一步降 embed/lm_head 浪费。

我的判断B 解锁的空间更大。 v5 的核心教训是「瓶颈在语料而非容量」——只放大模型A大概率撞上同一本 TinyStories 的信息天花板收益有限换更广语料B才是抬高天花板本身。理想的 v6 = A+B 同时(更大模型 吃更广语料),但若只能选一个,先 B广化语料

KI-3激活重计算是否需要:若 v6 走 Adim1024+ 更大模型),激活显存会显著上升,bf16 已经省了一半 v5 验证),但更大 batch/更长 seq 下仍可能吃紧 → 届时 KI-3激活重计算才成为下一个显存杠杆T12 文档 已把它列为「bf16 之后的下一个显存杠杆」)。若 v6 只走 B同 dim768 换语料),现有 bf16 + 缓存分配器够用, KI-3 暂不需要。即:KI-3 的触发条件 = v6 放大到 dim1024+,与 A 路线绑定。