Skip to content

第8章 · TinyGPT 预训练、恢复与生成

先修:第4章的 CE、第6章的优化器、第7章的 Transformer Block。

本章目标

  • 组装 token/position embedding、Transformer blocks、LM head、batch loader 和训练循环。
  • 先过拟合一个 batch,再在固定微型语料上训练、采样、保存和恢复。
  • 能解释 learning rate、batch、context、depth、width、梯度裁剪和 checkpoint 的作用;分布式训练只做口述。

公式与 shape

语言模型训练目标:

L(θ)=1BTb,tlogpθ(xb,t+1xb,t).

每次更新还要满足梯度裁剪上限 g ← g · min(1, c/||g||),checkpoint 至少保存模型、优化器、step、配置/数据/tokenizer hash。

对象shape说明
input ids(B, T)与 shifted targets 相差一个位置
token/position embeddings(B, T, D)位置索引不可越过 block size
logits(B, T, V)与 targets 对齐后算 CE
optimizer state与可训练参数相关resume 不能只加载 weights
checkpoint metadatamapping保存 step、config/data hash 和相对路径

数学桥接:第2章 → 第8章

第4章的 CE loss 是单 token 版本:logpθ(xt|x<t)。本章把它推广到整 batch 所有位置的平均:L=1BTb,tlogpθ(xb,t+1|xb,t)。两者的数学本质相同——都是 negative log-likelihood,只是 reduction 范围从单个 token 扩展到了整个训练集。

第2章 §7 的梯度裁剪 g ← g · min(1, c/||g||) 是本章训练稳定性的第一道防线。当梯度范数超过阈值 c 时,不改变梯度方向,只等比缩放——这比直接裁剪每个分量更合理(保持梯度之间的相对比例)。第2章的 `perplexity = 2^{CE}$ 是本章衡量生成质量的直觉指标:PP=1 表示模型每次都能 100% 预测正确,PP=100 表示平均每次在 100 个候选里猜。

Checkpoint 保存 optimizer state 是因为 AdamW 的 m^v^(第2章 momentum_update 的推广)需要跨 resume 保持连续——只加载 weights 不加载动量,恢复后的前几步梯度估计会偏。

前端类比:gradient clipping = CSS 的 max-height: 100vh; overflow: hidden——内容超出视口时不是删掉,而是等比缩放让整体可见。checkpoint = React 的 useReducer + localStorage——把整个 state(model + optimizer + step)序列化,刷新后精确恢复。

交互观察

交互:Softmax + Temperature

把 logits 看成「未归一化分数」。Temperature 越高分布越平,越低越尖。

tok0
8.5%
tok1
23.2%
tok2
5.2%
tok3
63.1%

LOCAL TRAINING TRACE · NO NETWORK

把一次 TinyGPT 更新拆成可回放事件

0%
batch取固定 seed 的 shifted input/target windowB=4 · T=16

当前是教学事件图,不执行 Python、不读取文件,也不代表云训练或学习者掌握。

把这里的 logits 视为生成器最后一步的输出,比较温度与 top-k 的职责;真正的 TinyGPT 生成还必须来自受控训练、checkpoint 和 token-level 对拍。

从零实践

  1. 用固定 byte 数据集做 one-batch overfit,记录初始 loss、最终 loss 和参数范数变化。

  2. 加入周期 checkpoint、恢复和 deterministic smoke;恢复后下一步的 loss/step 应与不中断轨迹一致到冻结容差。

  3. 运行当前必修训练测试:

    bash
    python -m pip install -r requirements.txt
    PYTHONPATH=python python -m pytest \
      python/tests/test_trainable_tinygpt.py \
      python/tests/test_checkpoint_recovery.py -q

    也可以用同一份脱敏 JSON 配置运行可复用的本地 CLI。它会执行真实 backward → AdamW → checkpoint,并在输出目录写入 evidence.json;默认 使用合成 byte 语料,不读取凭据或访问网络:

    bash
    PYTHONPATH=python python -m llm_train.cli \
      smoke --config configs/tiny-cpu.json --output-dir .artifacts/llm_train
    PYTHONPATH=python python -m llm_train.cli \
      inspect-checkpoint .artifacts/llm_train/tinygpt.pt

    CLI 输出的 status=ok 只表示这次本地训练和 checkpoint 结构通过;它不 代表云端资格、云服务部署或学习者 clean-room 掌握已经通过。

当前 python/llm_train/ 和上述测试已在 checkout 中存在,PyTorch 是规范安装的一部分。正式证据必须记录真实 backward/update、loss 下降、无 NaN、checkpoint 恢复和配置 hash;依赖缺失时应阻塞安装,而不是跳过训练 gate。

故障注入与预期信号

注入预期失败信号修复后证据
只执行 forward 不调用 optimizer参数差异为零,loss 不下降参数更新范数大于零且 loss 下降
target 未 shift模型学会复制当前位置shifted batch contract 失败并修复
梯度裁剪或 NaN gate 缺失训练出现非有限值仍退出 0NaN 使命令失败并保存可诊断结果

论文与延伸

前端/Agent 迁移

训练循环是带 telemetry 的事件循环:batch → forward → loss → backward → update → checkpoint。Agent 恢复同样不能只保存最终输出;要保存可重放的输入、状态版本、步数和副作用前后的 checkpoint。DP/TP/PP/ZeRO 只在本章用状态图和通信代价口述,不启动大规模训练。

口述与自测(不看资料,5–10 分钟)

  • (B, T) 的 input/target 写出 teacher forcing 的 shift 与 (B, T, V) logits 的 CE 对齐方式;解释 one-batch overfit 为什么是训练链路的必要诊断而不是泛化结论。
  • 对比 data parallel、tensor parallel、pipeline parallel 与 ZeRO:各自主要分摊什么、引入什么通信/显存代价;再说明 Scaling Laws 与 Chinchilla 不能由一次 tiny run 外推。
  • 用第2章的 perplexity(1.0) = 2.0 解释 TinyGPT 的 PP=2 意味着什么(平均每次在 2 个候选里猜);PP 从 10 降到 5 代表模型改进了多少。
  • 说明 gradient clipping(第2章 §7)和 learning rate schedule 分别是解决什么问题的——一个是梯度爆炸的"紧急刹车",一个是收敛精细调整的"巡航控制"。

实验与参考

动手实验

把 TinyGPT 从零训练跑通,并把检查点恢复做成可验证证据:训练损失单调下降、参数更新范数为正、按相同 config_hash 恢复后指标连续、CLI 输出单行 JSON 可被自动化消费。

环境准备

bash
cd <仓库>
export PYTHONPATH="$PWD/python"

命令与预期输出

smokeinspect-checkpoint 已在「从零实践」跑过,这里补上 examples 独有的 trainresume 子命令:

bash
# 用仓库内置 CPU 配置训练并落盘
python -m llm_train.cli train \
  --config configs/tiny-cpu.json \
  --output-dir .artifacts/llm_train

# 从最近一次 checkpoint 继续训练
python -m llm_train.cli resume \
  --resume-from .artifacts/llm_train/checkpoint.pt

# 可选参数:--text、--validation-fraction、--max-seconds
text
{"command":"train","status":"ok","steps":120,"initial_loss":4.51,
 "final_loss":3.12,"initial_validation_loss":4.48,
 "final_validation_loss":3.18,"parameter_update_norm":1.74,
 "checkpoint":".artifacts/llm_train/checkpoint.pt",
 "evidence":"train-20260810-101530","config_hash":"a91f...",
 "data_hash":"b3c2...","tokenizer_hash":"d401..."}

判定信号:
  final_loss < initial_loss 且 val loss 同步下降
  parameter_update_norm > 0(说明确实学到了东西)
  resume 前后 config_hash 一致,loss 曲线无跳变

概念图

图:第8章 TinyGPT 训练循环与 checkpoint 管理 — 第2章的 MLP 前向传播 + 交叉熵 + 梯度下降,加上第3–7章的 autograd、BPE、Transformer,在本章首次组装为"配置 → 训练 → checkpoint → 恢复"的完整生产闭环。后续第9章用 KV Cache 优化推理,第10章把 checkpoint 作为 SFT/LoRA 的起点,第13章把训练好的模型接入 Agent harness,第19章把 config_hash → checkpoint → eval → report 串成可审计 artifact chain。

故障注入清单

故障表现修复
忘记 optimizer zero_grad梯度累积导致 loss 抖动、指标不收敛每一步 optimizer.step 后立即 zero_grad
训练集与验证集切分泄漏val loss 异常低、看似过拟合其实数据穿帮严格按 hash 切分并固化随机状态
恢复时只 load 权重不 load optimizer state恢复后 loss 跳变、Adam 动量丢失同时 load 模型和 optimizer 状态
config_hash 与 checkpoint 不一致恢复到错误配置、shape 对不上恢复前先比对 hash、不一致则拒绝 resume

资源 / 成本 / 隐私

规范路径要求 PyTorch,优先 Apple Silicon MPS/CPU;本地训练预计 gross cost 为 0,不需要 Google Cloud。数据、checkpoint metadata 和 trace 只使用合成 fixture;云训练另走第18章的实时资格与一次性授权门。

Evidence

仓库当前机器证据(只读快照)

evidence/module-manifest-v1.json08.evidence 指向当前文件:evidence/08-runtime-v1.json。这是当前 checkout 的脱敏机器运行记录,只覆盖该 JSON 记录的命令、指标、产物和已知失败;它不是学习者提交,也不能推出学习者已完成本章。其 Python 3.11 运行范围、当前工作树边界和云端未核验状态以 JSON 的 known_failures 为准。

学习者提交模板(待填写,不是当前机器证据)

复制下面模板并填写自己的真实运行结果。所有 <...> 都是未填写状态;actualartifacts 尤其不能被当作已运行或已通过。artifacts 必须替换为本次提交中真实存在的仓库相对路径。

yaml
schema: learn-llm.evidence.v1
module: 08-tinygpt
commit: <learner-commit-sha>
verified_at: <iso-date>
environment: <sanitized-python-device-backend>
seed: 6
commands:
  - python -m pip install -r requirements.txt
  - PYTHONPATH=python python -m pytest python/tests/test_trainable_tinygpt.py python/tests/test_checkpoint_recovery.py -q
metrics:
  - name: parameter_update_norm
    expected: '>0'
    actual: <recorded-value>
  - name: final_loss_minus_initial_loss
    expected: '<0'
    actual: <recorded-value>
  - name: checkpoint_resume_max_error
    expected: <versioned-tolerance>
    actual: <recorded-value>
artifacts:
  - <learner-repo-relative-artifact-path>
cost:
  gross_usd: 0
  credit_usd: 0
licenses:
  - source: <source>
    version: <version>
    license: <license>
    attribution: <attribution>
    redistribution: <redistribution>
known_failures:
  - <sanitized-failure-or-none>

缺依赖、跳过测试、无参数更新或无恢复对拍时,本章保持 gate

私有学习站 · 原理从零构建 · 勿提交个人隐私或密钥