目录
前 23 课,我们把 Token、Attention、训练、推理和对齐拆开看。最后一课不再增加术语,而是把这些环节接起来。我们做一个能从头训练、能评估、能恢复训练、能通过本地接口生成文本的小型语言模型。
这个项目的目标是学会验证流程,不是做出 ChatGPT 的缩小版。模型只在短故事上训练,不会因此突然拥有聊天能力、事实知识或可靠的安全边界。
终期项目的合格线:别人拿到同一份代码、数据版本和配置,能复现你的训练过程,并看见你报告的成功与失败案例。
先把“做完”说清楚
我们选 TinyStories 这类短故事数据,训练一个小型 Decoder-only Transformer。TinyStories 是英文、由大模型生成的合成故事集,适合观察小模型能否学会基本的短文本结构;它不是通用语言能力的考试,更不是中文聊天数据。[1]
第一次运行,建议只用数据的一个固定子集、较短上下文和能在自己设备上跑通的模型。下面数字只是起步配置示例,不是性能承诺;硬件紧张就继续缩小,并把改动记下来。
| 项目 | 起步示例 | 为什么这样选 |
|---|---|---|
| 模型 | 约 1M~10M 参数的 Decoder-only Transformer | 足够观察完整训练链路 |
| 上下文 | 128~256 Token | 先控制注意力与显存开销 |
| 数据 | 固定版本的 TinyStories 子集 | 便于重跑与比较 |
| 输出 | 短故事续写 | 与训练目标一致 |
| 验收 | 验证 Loss、固定提示词样例、恢复测试、本地接口 | 不用“看起来会说话”代替证据 |
资源估算要在本机实测:参数量不是显存占用,优化器状态、激活、Batch 和上下文长度都会占空间。Stanford CS336 也把分词器、模型、优化器和最小语言模型训练作为一条完整实现链路。[2]
数据先定版,再训练分词器
第一步不是写模型,而是做一张数据记录卡:原始来源和版本、许可、下载日期、使用了哪些文件、过滤了什么、训练/验证怎么切。先按故事划分,再做训练和验证的去重检查,避免同一篇故事或高度相似的故事同时出现在两边。验证集从此冻结,后面不要因为结果不好就反复重切。
接着训练一个小词表的 BPE 分词器,保存词表、Merge 规则和特殊 Token ID。用固定的几句话检查:编码后是否能解码回原文;空字符串、标点和故事结束标记会怎样处理。这里的“可逆”要按分词器实际的规范化规则判断,不能只看一个漂亮例子。
产物至少有:数据清单、切分脚本、训练与验证文件的校验值、分词器文件、五条固定的 encode/decode 样例。读者拿到这些,才知道模型究竟看过什么。
先让模型记住 64 个样本
实现最小的 Decoder-only 结构:Token Embedding、位置处理、带因果遮罩的 Attention、FFN、残差、归一化,以及预测下一个 Token 的 LM Head。可以采用课程里学过的 RoPE、RMSNorm 和 SwiGLU,但不是一开始就必须把所有进阶组件装进去。先以最少的部件把前向、Loss 和反向传播跑通,再逐项替换和比较。
正式训练前,做一个很管用的“小测”:固定 64 个训练样本,反复训练它们。模型应该能明显降低这 64 个样本上的 Loss。如果连这件事都做不到,先查标签有没有错位、因果遮罩是否正确、梯度有没有更新、学习率是否离谱。不要直接扩大数据量来掩盖问题。
通过后再跑固定子集。每次实验记录代码版本、随机种子、数据与分词器版本、模型配置、优化器、有效 Batch、学习率曲线、训练/验证 Loss、梯度范数、耗时和峰值显存。固定种子能减少差异,但不能保证跨设备、跨 PyTorch 版本逐位一致。[3]
评估时,别只挑最好看的故事
训练 Loss 下降,只说明模型更会预测训练数据。主要结果应看冻结验证集的平均 Token Loss。Perplexity 可作为这个交叉熵的指数形式一起报告,但只有在相同数据处理、分词器和计算口径下才适合横向比较。
另外准备一组在实验开始前就写好的固定英文故事开头。每次评估用相同提示词、相同解码参数,展示至少三种结果:像样的续写、重复或崩坏的续写、明显记住训练文本的可疑片段。后者要回查数据,而不是当成能力进步。
把“验证 Loss 最低的 Checkpoint”和“人工看着最顺的样例”分开报告。如果中途多次改超参数,最好再留一份最终只看一次的测试集;别用同一份验证集既调参又宣称最终泛化效果。
故意中断一次,证明能继续
一个只保存模型权重的文件,通常不足以精确接着训练。还要保存优化器、学习率调度器、当前 Step、随机数状态、分词器与配置,以及必要的数据迭代位置。先跑一小段,手动中断,从最近的 Checkpoint 接着跑,检查下一步学习率和数据进度是否合理。
这里不要求不同机器的数值逐位相同;要求的是能解释恢复点、没有悄悄重置学习率、没有从头读数据却继续沿用旧 Step。把恢复前后的日志放在报告里,比写一句“支持断点续训”有说服力。
部署先从本机开始
为最佳 Checkpoint 做一个小接口:健康检查,以及输入一段故事开头、返回最多若干 Token 的续写。先用 Greedy 生成确认结果稳定,再试 Temperature/Top-P;KV Cache 可以作为优化实验,不是服务跑通的前提。比较同一提示词的输出是否一致,以及缓存前后每 Token 延迟、峰值内存的变化。
只绑定本机地址,例如 127.0.0.1;限制输入长度、最大输出长度和并发。日志记错误类型、时延和请求标识,默认不保存用户原文。若以后要开放到公网,还需要额外处理访问控制、限流、隐私与滥用风险;这不属于本课的默认交付。
至少测三项:首次 Token 延迟(TTFT)、后续每 Token 延迟,以及同时请求时的内存峰值。记下硬件、Batch、输入/输出长度和测量次数,否则孤立的“每秒多少 Token”没有可比性。
最终交什么?
把项目整理成别人能运行的仓库:README、锁定的环境、数据与许可说明、分词器、配置、训练和评估命令、恢复步骤、本地启动方式、曲线图、固定样例、失败案例和模型卡。模型卡要说清模型用途、数据来源、评估结果与已知局限;这也是公开模型时最基本的上下文。[4]
自己检查:现在真的能交付了吗?
完成 0 / 5 项。先补齐证据,再写“项目完成”。
勾选只帮你自查;页面不会验证你的代码,也不会保存勾选结果。
请特别写明:这是一个短故事续写模型,不是聊天助手。即使它能生成通顺句子,也不代表它具备事实问答、复杂推理或安全对齐能力。这个边界说清楚,项目才可信。
约 90 秒讲解视频
参考文献(References)
- Eldan, R., and Li, Y. “TinyStories: How Small Can Language Models Be and Still Speak Coherent English?” 2023. arXiv:2305.07759.↩
- Stanford University. “CS336: Language Modeling from Scratch.” 2025.↩
- PyTorch. “Reproducibility.” Documentation.↩
- Hugging Face. “Model Cards.” Documentation.↩
第二十四课复习总图
24 课到这里才算真正连成闭环:你不仅知道每个部件叫什么,还能解释它在一条可验证的训练与推理链路里起什么作用。