当前位置: 首页 > news >正文

一文讲清楚 Epoch、Batch 和 Iteration 的区别

一文讲清楚 Epoch、Batch 和 Iteration 的区别

刚开始训练深度学习模型时,很多同学都会被三个词绕晕:Epoch、Batch 和 Iteration。训练命令里写着 epochs=100batch=16,日志中又不断出现 1/10063/63。它们看上去都在计数,却分别在数什么?有人把 100 个 Epoch 理解成模型只更新 100 次,也有人以为 Batch Size 越大,模型看到的数据就越多。

这三个概念其实处在同一条训练链路上。Batch 决定模型一次处理多少条数据,Iteration 记录训练循环执行了多少次,Epoch 表示训练集被完整遍历了多少轮。下面用一个固定例子贯穿全文:训练集有 1000 张图片,Batch Size 设置为 32,一共训练 100 个 Epoch。把这组数字算明白,以后再看 YOLO 或其他模型的训练日志就容易多了。

一、先把三者放回同一条训练链路

先看 Epoch。在常见的训练方式中,模型把训练集中的全部样本都学习一遍,就完成了 1 个 Epoch。训练集有 1000 张图片,跑完 1 个 Epoch,通常意味着这 1000 张图片都参与了一轮训练。设置 100 个 Epoch,相当于让模型围绕这批训练数据学习 100 轮。

但显卡通常装不下整个训练集,模型也没有必要等到看完 1000 张图片才更新一次参数。训练程序会把数据拆成许多小组,每组数据就是一个 Batch。Batch Size 为 32,表示程序每次取出 32 张图片送入模型。目标检测任务里,一张图片无论包含 1 个目标还是 20 个目标,在计算 Batch Size 时都只算一个样本。

程序取出一个 Batch,完成前向传播、损失计算和反向传播,这一轮训练循环通常称为一次 Iteration,也经常写成 Step。在没有使用梯度累积等特殊设置时,一次 Iteration 往往伴随一次参数更新。

把层级关系连起来看,就是下面这条链路:

  • 一个训练集被拆成多个 Batch。
  • 模型处理一个 Batch,完成一次 Iteration。
  • 模型处理完当前轮次的全部 Batch,完成一个 Epoch。

因此,Epoch 管的是完整轮次,Batch 管的是每次取多少样本,Iteration 管的是内部训练循环走了多少步。三者的计数范围不同,不能互相替换。

二、用 1000 张图片算清一个 Epoch

回到开头的例子。训练集共有 1000 张图片,Batch Size 为 32。

前 31 个 Batch 可以装下 992 张图片,因为 31 乘以 32 等于 992。训练集还剩 8 张图片,它们会组成最后一个较小的 Batch。因此,模型完整看完这 1000 张图片,需要执行 32 次 Iteration。

在默认保留最后一个不足 Batch 的情况下,可以这样计算:

每个 Epoch 的 Iteration 数 = 向上取整(训练样本数 ÷ Batch Size)

代入例子:

每个 Epoch 的 Iteration 数 = 向上取整(1000 ÷ 32)= 32

如果训练 100 个 Epoch,那么整个训练过程计划执行的 Iteration 数为:

总 Iteration 数 = Epoch 数 × 每个 Epoch 的 Iteration 数

也就是:

100 × 32 = 3200 次 Iteration

这时,epochs=100 并不表示模型只更新 100 次。在普通训练设置下,模型会更新大约 3200 次。Epoch 只负责统计数据集被完整学习了多少轮,真正频繁发生的参数调整位于一个个 Iteration 中。

如果训练集刚好有 1024 张图片,Batch Size 仍然为 32,那么 1024 除以 32 正好等于 32,最后一个 Batch 也是完整的。很多人计算时容易忽略最后一批余数,所以实际日志中的 Batch 总数偶尔会比手算结果多 1。

三、一次 Iteration 内部发生了什么

Iteration 容易被理解成一个单纯的计数单位。实际上,它对应着模型的一次完整学习动作。

程序先从数据加载器中取出一个 Batch。以 Batch Size 为 32 为例,这一步会得到 32 张图片及其标签。图片经过模型后产生预测结果,这叫前向传播。随后,程序将预测结果与真实标签进行比较,计算当前 Batch 的损失。

有了损失,模型开始反向传播。程序计算各个参数应该朝哪个方向调整,以及大致调整多少。优化器再根据这些梯度更新模型参数。梯度清零之后,程序继续读取下一个 Batch。

一次常见的 Iteration 可以概括为五个动作:

  • 读取一个 Batch;
  • 执行前向传播;
  • 计算损失;
  • 执行反向传播;
  • 更新模型参数并准备处理下一批数据。

这也解释了模型为什么能够逐渐学会任务。它不会等到一个 Epoch 完成后才统一总结,而是每处理一批数据就获得一次修正机会。后面的 Batch 使用的是已经更新过的模型参数,所以同一个 Epoch 内,模型也在持续变化。

验证阶段同样会把数据拆成多个 Batch,也会执行多次前向计算。不过验证过程通常不做反向传播,也不更新参数。训练日志中即使出现验证 Step,也不能把它计入训练参数的更新次数。

四、Batch Size 改变后,训练过程会怎样变化

训练集大小不变时,Batch Size 会直接改变每个 Epoch 中的 Iteration 数。

仍以 1000 张图片为例。Batch Size 为 32 时,每个 Epoch 需要 32 次 Iteration;改成 16 后,每个 Epoch 需要 63 次;改成 64 后,每个 Epoch 只需要 16 次。Batch 越大,每轮训练中的 Iteration 越少,但单次计算要同时处理更多图片。

这种变化首先体现在显存上。Batch Size 增大后,模型需要同时保存更多图片的特征、预测结果和梯度,中间计算结果占用的显存也会增加。显存不足时,训练程序往往直接报错。对刚开始训练 YOLO 的同学来说,遇到显存溢出,降低 Batch Size 通常是最直接的处理办法。

Batch Size 还会改变梯度的特点。较大的 Batch 汇总了更多样本的信息,得到的梯度通常更平稳;较小的 Batch 含有更明显的随机波动,但每个 Epoch 能进行更多次参数更新。两者各有代价,不能只根据“越大越快”或“越小越容易泛化”来做决定。

更换 Batch Size 后,学习率和训练轮数也可能需要重新评估。比如两个实验都训练 100 个 Epoch,一个使用 Batch Size 16,另一个使用 Batch Size 64。虽然它们都把训练集学习了 100 轮,前者的参数更新次数大约是后者的四倍。只比较 Epoch 数,无法说明两个模型接受了完全相同的优化过程。

Epoch 主要决定训练数据被重复利用多少轮。轮数太少,模型可能还没有充分学习;轮数继续增加,训练集表现可能越来越好,验证集表现却开始下降,这通常是过拟合的信号。训练时设置的 Epoch 更像一个计划上限。如果启用了早停,验证指标长时间没有改善,程序可能在达到上限之前结束训练。

Iteration 则更贴近模型的参数更新节奏。学习率调度器何时下降、日志多久打印一次、模型多久保存一次,有些框架按 Epoch 控制,有些配置会按 Iteration 或 Step 控制。看配置文件时先确认计数单位,可以避免把“每 100 个 Step 调整一次”误读成“每 100 个 Epoch 调整一次”。

五、为什么实际日志中的数字有时和公式对不上

前面的计算建立在最常见的训练方式上。实际项目里还有几个设置会改变三者的对应关系。

第一种情况是丢弃最后一个不完整的 Batch。数据加载器通常有一个类似 drop_last 的选项。1000 张图片按每批 32 张划分,最后会剩下 8 张。如果保留这 8 张,每个 Epoch 有 32 个 Batch;如果开启丢弃选项,每个 Epoch 只剩 31 个 Batch。

丢弃最后一批不代表那 8 张图片永远不会参与训练。数据在每个 Epoch 开始前通常会重新打乱,因此每轮被留到末尾的样本可能不同。不过,对于数据量本来就很少的项目,是否丢弃仍然值得认真考虑。

第二种情况是梯度累积。显存只能容纳 16 张图片,但我们希望获得接近 Batch Size 64 的更新效果,可以连续处理 4 个小 Batch,先把梯度累积起来,再调用一次优化器更新。此时训练循环已经执行了 4 次,参数却只更新了 1 次。

在这个场景中,Iteration 和参数更新次数不再严格相等。有人把每个小 Batch 叫作一次 Iteration,把真正调用优化器更新的时刻叫作一次 Optimizer Step;也有日志把两者都称为 Step。遇到梯度累积时,需要查看框架具体在统计什么。

有效 Batch Size 可以粗略写成:

有效 Batch Size = 单设备 Batch Size × 设备数量 × 梯度累积次数

例如,两张显卡各处理 16 张图片,每累计 2 次再更新参数,有效 Batch Size 就是 64。不同训练框架中的 batch 参数可能表示单卡数量,也可能表示全局数量,不能只凭参数名判断。

第三种情况是人为规定每个 Epoch 的 Step 数。普通数据加载器会在数据耗尽时结束当前 Epoch。如果使用无限数据流、重复采样器,或者手动设置了 steps_per_epoch,一个 Epoch 可以在规定的 Step 数到达后结束。这时,Epoch 更像人为划定的训练区间,未必对应一次严格的全量数据遍历。

还有一个容易忽略的因素是随机打乱和数据增强。即使源数据仍然是同一批图片,每个 Epoch 的读取顺序通常不同,随机裁剪、颜色变化、Mosaic 等增强结果也可能变化。因此,模型每轮看到的训练输入不会完全一样,但源数据集依旧完成了一轮遍历。

六、怎样看懂 YOLO 训练日志里的这些数字

假设某个 YOLO 数据集有 1000 张训练图片,Batch Size 设置为 16。保留最后一个不完整 Batch 时,每个 Epoch 需要:

向上取整(1000 ÷ 16)= 63 次 Iteration

训练日志中出现 Epoch 1/100,表示当前正在执行第 1 个 Epoch,计划上限为 100 个 Epoch。进度条中的 63/63 通常表示这一轮共有 63 个 Batch,当前已经处理到最后一个。进入 Epoch 2/100 后,Batch 进度会重新从开头计数。

如果把 Batch Size 改为 32,同一个数据集每轮只需要 32 次 Iteration。你会发现每个 Epoch 的进度条变短了,但每次 Iteration 处理的图片更多,显存占用也随之变化。单个 Epoch 是否更快,还会受到数据读取、显卡利用率、输入尺寸和数据增强开销影响,不能只看 Iteration 数下结论。

阅读日志时,可以顺手核对四个信息:训练集实际有多少张图片,Batch Size 最终是多少,每个 Epoch 有多少个 Iteration,训练是否使用了梯度累积或多卡。把这四项记入实验记录,很多看似异常的日志数字都能解释清楚。

做模型对比时,也建议同时记录 Epoch、Batch Size 和总参数更新次数。只写“两个模型都训练了 100 个 Epoch”,信息并不充分。Batch Size、设备数量、梯度累积和早停时刻不同,模型经历的优化过程就可能存在明显差异。

结语

记住三句话就够了:Batch 表示模型一次拿多少条数据,Iteration 表示训练循环处理了多少个 Batch,Epoch 表示训练集被完整学习了多少轮。在普通设置下,一个 Batch 对应一次 Iteration,也对应一次参数更新;加入梯度累积、多卡训练或自定义 Step 后,这种对应关系会发生变化。以后看到 epochs=100batch=16 或日志中的 63/63,先把训练样本数代入计算,再确认特殊配置,三组数字就不会混在一起了。