① 为什么不一次用全部数据
全量数据(Full-batch)虽然梯度准确,但内存放不下、计算太慢、更新次数太少。几十亿 token 的语料不可能一次性送进模型。
前面我们已经集齐了所有零件:Token、Embedding、Attention、交叉熵、自动微分、优化器。但模型不是看一遍数据就能学会——它需要把同样的数据反复看很多遍,每次只看一小批,一遍又一遍地“前向 → 算损失 → 反向 → 更新”。这一页会把这条训练流水线完整拆开,让你亲手控制它、观察它。
前面页面的单次“前向 → 反向 → 更新”只是走了一小步。真实训练需要重复这个过程成千上万次。这就引出了三个核心概念:Batch(每次看多少样本)、Iteration(更新一次参数)、Epoch(把所有数据完整看一遍)。
全量数据(Full-batch)虽然梯度准确,但内存放不下、计算太慢、更新次数太少。几十亿 token 的语料不可能一次性送进模型。
单样本(SGD)虽然更新频繁,但梯度噪声极大、方差高,训练不稳定,且 GPU 利用率极低。
每次取几十到几千个样本,既保证梯度足够稳定,又兼顾内存、速度和 GPU 并行效率。这是深度学习的标准做法。
下面是一个模拟训练环境。数据集有 12 个样本,模型每次从数据集中取一个 Batch 进行学习。你可以调整 Batch Size,观察 Iteration 数量怎么变,然后点击“开始训练”看完整的 Epoch 循环。
每个方块代表一个样本。蓝色表示当前 Batch 正在使用,绿色表示本轮已学过,黄色表示验证集样本(不参与训练)。
每个 Batch 都要完整走完这四步。绿色表示已完成,蓝色表示当前正在执行。
每个更新步后记录一次损失。整体趋势下降,说明模型在学会拟合数据。
训练循环里有四个容易混淆的概念。下面用一张表把它们彻底区分开。
| 概念 | 含义 | 决定什么 | 典型值 |
|---|---|---|---|
| Batch Size | 一次前向/反向中使用的样本数量 | 梯度稳定性、内存占用、训练速度 | 32 ~ 4096 |
| Iteration | 处理一个 Batch 并更新一次参数 | 参数被更新了多少次 | 每 Epoch 有 N/B 次 |
| Epoch | 把所有训练数据完整遍历一遍 | 模型看了几遍数据 | 1 ~ 100+ |
| Shuffle | 每个 Epoch 开始前打乱数据顺序 | 防止模型记住样本顺序,提升泛化 | 通常开启 |
问题: 如果数据按固定顺序排列(比如所有“好”的样本在前,所有“坏”的样本在后),每个 Batch 的分布会严重偏斜。模型会在一个 Batch 里只看到一种模式,梯度方向剧烈摆动。
解决: 每个 Epoch 开始前把数据随机打乱,让每个 Batch 都包含多样化的样本。梯度更接近真实分布,训练更稳定,泛化更好。
注意: 验证集和测试集不能 shuffle,因为需要稳定的评估结果。有些任务(如时间序列)还需要按时间顺序划分,不能用随机 shuffle。
问题: 训练损失下降不代表模型真的学会了。它可能只是把训练数据“背下来”了,遇到新数据就废了。这就是过拟合。
解决: 从数据中划出一小部分作为验证集,不参与训练。每个 Epoch 结束后在验证集上算一次损失。如果训练损失还在降、验证损失开始升,就说明过拟合了,需要早停、正则化或更多数据。
在 LLM 中: 预训练通常用困惑度(perplexity)作为验证指标。验证损失持续上升时,会触发早停或调整学习率。
下面用六张卡片,把训练循环相关的每一个概念完整讲清楚。你可以按顺序读,也可以挑自己最关心的部分看。
训练循环(Training Loop)是深度学习训练的核心控制流程。它反复执行“取一批数据 → 前向传播 → 计算损失 → 反向传播 → 更新参数”这一组操作,直到达到预设的 Epoch 数或满足早停条件。
Batch Size 是每次前向/反向使用的样本数。Iteration 是处理一个 Batch 并更新一次参数的过程。Epoch 是把所有训练数据完整遍历一遍。Shuffle 是每个 Epoch 开始前打乱数据顺序的操作。Dataloader 是负责按 Batch 取数据、Shuffle、并行加载的组件。
在 PyTorch 中,典型写法是嵌套循环:外层是 Epoch,内层是 Dataloader 产出的 Batch。在 LLM 训练中,数据通常被预先 tokenize 成固定长度的序列,然后按 Batch 送入模型。
想象你要背一本单词书。你不会一口气把整本书塞进脑子,也不会每次只背一个单词。你会把书分成若干组,每组背十几个,背完一组就回头复习一下,然后继续下一组。背完一整本书,算“一遍”。
Batch Size 就是每组背多少个单词。Iteration 是背完一组并调整记忆。Epoch 是把整本书背完一遍。Shuffle 是每次重新开始背的时候打乱单词顺序,免得你只记住了顺序而不是单词本身。
训练模型也是一样:把数据分成小批,一批一批地学,一遍一遍地复习。每次复习后,模型的参数都会往“更正确”的方向调整一点。
它解决了“如何用有限的内存和计算资源,高效地遍历大规模数据集并反复更新模型”这个问题。
训练循环是连接“模型结构”和“优化器”的胶水。没有它,再好的模型和优化器也只是静态的组件,无法真正从数据中学习。
它决定了:
在大模型训练中,数据加载、梯度累积、分布式采样、检查点保存等都围绕着训练循环展开。理解训练循环,是理解整个训练系统的前提。
越大越稳但更新越少、内存越高;越小更新越频繁但噪声越大。没有绝对最优,需要按任务和硬件调。
传统机器学习可能要几十上百个 Epoch,但 LLM 预训练通常 1~3 个就够。关键是看验证损失有没有继续下降。
Shuffle 保证梯度质量,验证集监控过拟合。这两个小细节对最终模型质量影响巨大,不值得为了省事跳过。