Page 33 · SimLabs LLM Visual

训练循环、Batch 与 Epoch:模型是怎样被反复喂养的

前面我们已经集齐了所有零件:Token、Embedding、Attention、交叉熵、自动微分、优化器。但模型不是看一遍数据就能学会——它需要把同样的数据反复看很多遍,每次只看一小批,一遍又一遍地“前向 → 算损失 → 反向 → 更新”。这一页会把这条训练流水线完整拆开,让你亲手控制它、观察它。

看懂训练循环 理解 Batch 与 Iteration 掌握 Epoch 与 Shuffle 亲手跑一次完整训练

一次更新远远不够

前面页面的单次“前向 → 反向 → 更新”只是走了一小步。真实训练需要重复这个过程成千上万次。这就引出了三个核心概念:Batch(每次看多少样本)、Iteration(更新一次参数)、Epoch(把所有数据完整看一遍)。

取一批数据 → 前向传播 → 算损失 → 反向传播 → 更新参数 → 重复

① 为什么不一次用全部数据

全量数据(Full-batch)虽然梯度准确,但内存放不下、计算太慢、更新次数太少。几十亿 token 的语料不可能一次性送进模型。

② 为什么也不一次只用一个样本

单样本(SGD)虽然更新频繁,但梯度噪声极大、方差高,训练不稳定,且 GPU 利用率极低。

③ Mini-batch 是折中

每次取几十到几千个样本,既保证梯度足够稳定,又兼顾内存、速度和 GPU 并行效率。这是深度学习的标准做法。

先抓住一句话: Batch 决定“每次看多少”,Iteration 是“更新一次参数”,Epoch 是“把所有数据完整看一遍”。训练就是在 Epoch 里循环 Iteration,直到模型学会为止。

实验台:亲手跑一次训练循环

下面是一个模拟训练环境。数据集有 12 个样本,模型每次从数据集中取一个 Batch 进行学习。你可以调整 Batch Size,观察 Iteration 数量怎么变,然后点击“开始训练”看完整的 Epoch 循环。

Epoch 0 / 3
Batch 0 / 4
总更新步 0
等待开始

1数据集:12 个训练样本

每个方块代表一个样本。蓝色表示当前 Batch 正在使用,绿色表示本轮已学过,黄色表示验证集样本(不参与训练)。

当前 Batch 本轮已学 验证集

2训练循环:4 个阶段反复执行

每个 Batch 都要完整走完这四步。绿色表示已完成,蓝色表示当前正在执行。

① 前向传播 → ② 计算损失 → ③ 反向传播 → ④ 更新参数 ↻
// 训练日志将在这里显示

3损失曲线:模型有没有在进步

每个更新步后记录一次损失。整体趋势下降,说明模型在学会拟合数据。

更新步数 → —

控训练参数

3
3
0.12
训练集:10 个样本
验证集:2 个样本
每轮 Iteration 数:4
总更新步数:12
// 训练循环伪代码
for epoch in range(num_epochs):
  shuffle(dataset) // 打乱顺序
  for batch in dataloader:
    loss = forward(batch)
    grad = backward(loss)
    optimizer.step(grad)
观察提示: 把 Batch Size 从 1 调到 6,看每轮的 Iteration 数怎么变。Batch Size 越大,更新步数越少,但每步计算量越大。这就是“训练速度”与“梯度质量”之间的权衡。

四个概念,一次讲清

训练循环里有四个容易混淆的概念。下面用一张表把它们彻底区分开。

概念 含义 决定什么 典型值
Batch Size 一次前向/反向中使用的样本数量 梯度稳定性、内存占用、训练速度 32 ~ 4096
Iteration 处理一个 Batch 并更新一次参数 参数被更新了多少次 每 Epoch 有 N/B 次
Epoch 把所有训练数据完整遍历一遍 模型看了几遍数据 1 ~ 100+
Shuffle 每个 Epoch 开始前打乱数据顺序 防止模型记住样本顺序,提升泛化 通常开启
它们的关系: 假设数据集有 1000 个样本,Batch Size = 100,Epoch = 10。那么每个 Epoch 有 10 个 Iteration,总共 100 次参数更新,模型把数据完整看了 10 遍。

Shuffle 与验证集:两个容易被忽略但很重要的细节

🔀 Shuffle:为什么每个 Epoch 要打乱顺序

问题: 如果数据按固定顺序排列(比如所有“好”的样本在前,所有“坏”的样本在后),每个 Batch 的分布会严重偏斜。模型会在一个 Batch 里只看到一种模式,梯度方向剧烈摆动。

解决: 每个 Epoch 开始前把数据随机打乱,让每个 Batch 都包含多样化的样本。梯度更接近真实分布,训练更稳定,泛化更好。

注意: 验证集和测试集不能 shuffle,因为需要稳定的评估结果。有些任务(如时间序列)还需要按时间顺序划分,不能用随机 shuffle。

📊 验证集:怎么知道模型有没有过拟合

问题: 训练损失下降不代表模型真的学会了。它可能只是把训练数据“背下来”了,遇到新数据就废了。这就是过拟合。

解决: 从数据中划出一小部分作为验证集,不参与训练。每个 Epoch 结束后在验证集上算一次损失。如果训练损失还在降、验证损失开始升,就说明过拟合了,需要早停、正则化或更多数据。

在 LLM 中: 预训练通常用困惑度(perplexity)作为验证指标。验证损失持续上升时,会触发早停或调整学习率。

在真实 LLM 训练里: 一个 Epoch 可能意味着遍历几百 GB 的 token 数据。训练通常不会跑很多 Epoch(1~3 个就够),因为数据量极大,模型见过一遍就已经学到很多。这和传统机器学习里动辄几十上百个 Epoch 很不一样。

知识点完整总结

下面用六张卡片,把训练循环相关的每一个概念完整讲清楚。你可以按顺序读,也可以挑自己最关心的部分看。

📖 标准介绍

训练循环(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 是每次重新开始背的时候打乱单词顺序,免得你只记住了顺序而不是单词本身。

训练模型也是一样:把数据分成小批,一批一批地学,一遍一遍地复习。每次复习后,模型的参数都会往“更正确”的方向调整一点。

🔧 解决了什么问题

它解决了“如何用有限的内存和计算资源,高效地遍历大规模数据集并反复更新模型”这个问题。

  • 内存限制:全量数据无法一次性放入 GPU 显存,必须分批加载。
  • 计算效率:小批量能充分利用 GPU 并行能力,同时保持梯度质量。
  • 更新频率:Batch Size 越小,单位数据内的参数更新次数越多,收敛越快(但噪声也越大)。
  • 泛化能力:适度的 Batch Size 和 Shuffle 能带来正则化效果,提升泛化。
  • 训练可控:通过 Epoch、验证集、早停等机制,可以监控和终止训练过程。

⭐ 为什么重要

训练循环是连接“模型结构”和“优化器”的胶水。没有它,再好的模型和优化器也只是静态的组件,无法真正从数据中学习。

它决定了:

  • 模型需要多长时间才能收敛;
  • 训练过程是否稳定(会不会出现 loss spike 或 NaN);
  • 模型最终能否泛化到新数据;
  • 训练需要多少显存、多少 GPU、多少时间;
  • 整个训练流程是否可复现、可调试、可扩展。

在大模型训练中,数据加载、梯度累积、分布式采样、检查点保存等都围绕着训练循环展开。理解训练循环,是理解整个训练系统的前提。

🚀 应用场景

  • LLM 预训练:遍历数万亿 token,Batch Size 可达数百万 token,训练数周。
  • LLM 微调:SFT、LoRA、DPO 等,通常 1~3 个 Epoch。
  • 计算机视觉:ImageNet 训练通常 90~300 个 Epoch,Batch Size 256~4096。
  • 语音识别:序列数据需要动态 Batch 和 Padding。
  • 推荐系统:在线训练中,Batch 可能来自实时数据流。
  • 强化学习:训练循环嵌套在环境交互中,Batch 来自经验回放池。
  • 联邦学习:每个客户端本地跑训练循环,再聚合梯度。

⚠️ 缺陷与局限

  • Batch Size 敏感:太大导致泛化变差、更新次数太少;太小导致梯度噪声大、训练不稳定、GPU 利用率低。需要根据任务和硬件调优。
  • Epoch 数难定:太少欠拟合,太多过拟合。需要验证集监控和早停策略。
  • Shuffle 有代价:大规模数据随机读取会降低 I/O 效率,需要预取、缓存、分片等技术配合。
  • 数据顺序仍有影响:即使 Shuffle,某些任务中样本顺序仍会影响最终模型。课程学习(Curriculum Learning)会刻意设计顺序。
  • 验证集划分有讲究:时间序列、用户行为等数据不能随机划分,否则会数据泄露。需要按时间、按用户等策略划分。
  • 分布式训练复杂:多卡训练时,Batch 被切分到不同设备,梯度需要 AllReduce,训练循环逻辑更复杂。
  • 梯度累积:显存放不下大 Batch 时,用多个小 Batch 累积梯度再更新,但需要调整学习率和 BatchNorm 行为。
一句话理解训练循环: 把数据切成小批,一批一批地喂给模型,每喂一批就纠正一次参数,喂完一整遍算一个 Epoch,反复多遍直到模型学会。Batch Size 决定每次看多少,Iteration 决定更新多少次,Epoch 决定看几遍,Shuffle 决定顺序怎么打乱。这就是所有深度学习训练的基本节奏。

学完这一页,最好记住三件事

Batch Size 是权衡

越大越稳但更新越少、内存越高;越小更新越频繁但噪声越大。没有绝对最优,需要按任务和硬件调。

Epoch 不是越多越好

传统机器学习可能要几十上百个 Epoch,但 LLM 预训练通常 1~3 个就够。关键是看验证损失有没有继续下降。

Shuffle 和验证集别省

Shuffle 保证梯度质量,验证集监控过拟合。这两个小细节对最终模型质量影响巨大,不值得为了省事跳过。