Skip to content

训练:把正确梯度变成可复现实验 ​

训练语言模型不只是循环调用优化器。你需要明确监督目标、数据抽样、归一化、更新规则和验证协议。这里逐步拆解 labs/llm/train.py,让每个日志数字都有清楚的含义;在此基础上再扩大模型和语料,才知道一次失败来自哪里。

输入与目标严格错开一位 ​

从 token 流取长度 T+1 的窗口 [a,b,c,d,e],输入是 [a,b,c,d],目标是 [b,c,d,e]。输入的每个位置都获得一个预测任务,因果 mask 保证第一个位置只能利用 a 预测 b,第二个位置利用 a,b 预测 c。本地 make_batch 返回 [B,T] 的两张整数表,测试用递增序列验证 y == x + 1,避免只检查形状。

跨文档拼接需要定义边界。真实训练通常插入文档结束标记,并决定是否屏蔽跨文档注意力。本地原创短句按换行连接,没有独立 EOS;模型学习的是这段连续短句流,不应解释为通用文档 packing 实现。训练和验证先按行分开,再分别编码,不从同一个随机滑窗池中划分,否则相邻窗口高度重叠,会把几乎相同的文本泄漏到两边。

loss 与 batch 的尺度 ​

训练目标为 L=−1BT∑b,tlog⁡pθ(yb,t∣xb,≤t)。如果有 padding,应除以有效 token 总数。梯度累积时,K 个等长 microbatch 的 loss 各除以 K,然后累积一次更新;不等长时应按有效 token 数加权,而非简单平均每批均值。

perplexity 是 exp⁡(L),使用自然对数时成立。它可以读成“平均不确定性”的一种指数化表达,但不是模型每步真的只在这么多个词之间选择。比较不同 tokenizer 必须谨慎;相同验证文本、相同 tokenization 和同一 loss mask,才构成干净比较。

AdamW 在做什么 ​

对梯度 gt,Adam 维护一阶、二阶指数移动平均:

mt=β1mt−1+(1−β1)gt,vt=β2vt−1+(1−β2)gt2.

初始均为零,因此用 m^t=mt/(1−β1t)、v^t=vt/(1−β2t) 修正早期偏差。AdamW 将权重衰减与自适应梯度分开:

θt+1=(1−ηtλ)θt−ηtm^tv^t+ϵ.

把 λθ 混入梯度再交给 Adam,通常不等价于这个更新,因为衰减也会被二阶矩缩放。本地仅衰减矩阵,归一化 gain 不衰减;这个选择要写进配置。一次有限梯度测试不能检验优化器状态,故还做了固定小批次过拟合测试,确认模型能够持续优化同一目标。

裁剪与学习率 ​

全局梯度范数 r=∑i∥gi∥2 超过阈值 c 时,把全部梯度乘 c/r。它保留整体方向,限制异常一步的大小。逐个参数独立裁剪会改变方向,不是同一种操作。日志记录的是裁剪前范数,便于判断训练是否长期依赖裁剪。

学习率先线性 warmup,再 cosine decay 到最大值的 10%。warmup 不会修复错误梯度,但能降低优化器早期状态不稳定带来的冲击。学习率过大可能让 loss 爆炸,过小则可能看似稳定但几乎没有学习。诊断顺序应是:确认数据和梯度正确;小批次能否过拟合;再调学习率、初始化和批大小。

flowchart LR
  A[固定 seed 抽样窗口] --> B[前向与平均 NLL]
  B --> C[反向传播]
  C --> D[记录范数并裁剪]
  D --> E[调学习率 AdamW]
  E --> A
  E --> F[固定验证窗口 记录日志]
查看流程图文本
flowchart LR
  A[固定 seed 抽样窗口] --> B[前向与平均 NLL]
  B --> C[反向传播]
  C --> D[记录范数并裁剪]
  D --> E[调学习率 AdamW]
  E --> A
  E --> F[固定验证窗口 记录日志]

checkpoint 应包含什么 ​

推理最少需要参数、模型配置、tokenizer;精确恢复训练还需要优化器的一二阶矩、步数、随机数状态、数据游标、学习率调度状态。当前 .npz 保存的是推理 checkpoint,不承诺从中恢复完全一致的训练轨迹。文件以 allow_pickle=False 读取,元数据使用 JSON;这也让配置可以直接检查。

本地 metrics.json 记录语料 SHA-256、Python/NumPy 版本、seed、参数量、训练/验证规模、定期 NLL 和生成样本。seed 固定能提高复现性,但换 BLAS、硬件、线程数仍可能产生浮点差异。测试应该允许小数值误差,而非要求跨平台日志逐字节一致。

一次真实小实验如何解释 ​

本仓库实测默认字符模型在 seed 7、300 步时,固定训练窗口 NLL 从约 3.899 降至 0.733,验证窗口从约 3.861 降至 1.266。它说明训练闭环有效;末期验证没有随训练同步改善,提示小语料上的泛化收益开始变弱。这里的指标只是 32 个固定抽样验证窗口,不是整个验证集的无偏精确评分,更不代表真实语言建模基准。完整记录见 实验手册。

自测 ​

batch 翻倍,loss 仍是平均值,梯度为什么还可能变化?

平均消除了直接的倍数关系,但样本组成改变会降低或改变梯度估计噪声,新增窗口也会改变平均方向。若使用 dropout 或不同 packing,差异更多。只有将完全相同的一批复制一次,并保持其它行为一致时,平均梯度才应基本不变。

train loss 下降、validation loss 上升,应该首先增加模型宽度吗?

先检查数据泄漏、验证协议和训练步数,再考虑过拟合与数据分布偏移。更大模型可能加重问题;早停、更多高质量训练数据、合适正则化与匹配的验证集通常更直接。不能凭单个 noisy batch 判定趋势。

来源:AdamW 论文、官方 A1 2025。下一章:生成与推理。