先让它学会

坐下 4 / 6

循环只有三拍。曲线告诉你第几拍坏了。

梯度算对只完成一半。还要按固定顺序更新,并且真的在看两条损失,而不是只盯训练数字往下掉就鼓掌。

zero_grad → backward → step

PyTorch 默认把梯度累加。一个 mini-batch 用完,下一步若不清零,新梯度会叠在旧的上面,步子越走越怪。典型一拍:

for x, y in loader:
    opt.zero_grad(set_to_none=True)
    loss = criterion(model(x), y)
    loss.backward()
    opt.step()

backward 只填 .grad,不改参数。step 才按学习率去减。把 zero_grad 写在 step 之后且下一次循环开始前也行,前提是你清楚「这轮用的是刚算的那份」。写丢其中一拍,曲线会给你三种常见样子:不动、乱跳、训练损失假下降。

学习率 0.1 在上一页那个五参数例子里,损失从 0.211 降到 0.108。换成 10,一步就可能越过谷底,损失变大。换成 1e-8,五十步看起来像一条平线。先用能在十步内拉动训练损失的步长,再谈 Adam 的 β。

先过拟合一个小集合

拿 8 到 32 个样本、关掉随机增强、把模型开得略大,故意让它把这一小撮记住。训练损失应能降到接近 0,训练准确率顶到 1。这一步过不了:标签和 logits 对错轴、学习率炸了、忘了 model.train()、损失接到了常数。先修管道,再谈泛化。

管道通了,再打开验证集。验证损失用于挑何时停。测试集仍封着。不要用验证曲线的最低点去对外宣传——那是选择模型用的,不是最终估计。shuffle 只打乱训练;验证按固定顺序,曲线才能和上次比。batch 从 32 改到 2,损失噪声会变大,看起来像没收敛,其实只是估计变差。先固定 batch 再谈学习率。

三条线分别叫什么

训练降、验证降:还在学。若两者一起降但停在很高的地方,容量不够或标签噪声大,先别加 dropout,那会再挡一层。

训练降、验证升:记住训练样本了。停早、加数据、加一点权重衰减。继续报训练损失没有意义。

两条都平:学习率太小像没走;太大通常先抖再变 NaN;也可能 zero_grad 没写、目标是错的、把准确率当损失在最小化。先印几个 batch 的 loss 原始值。从第一步起就是 0 或 NaN,是代码,不是「还需要更多 epoch」。交叉熵第一步常在 log K 附近:十类约 2.3。一上来就是 1e-5,多半标签和 softmax 接反了。

给三条草图起名

实线训练,虚线验证。点选名称。

自己对过

一起降:还在学。分叉:过拟合。卡住:先查学习率和那三拍有没有写全。