Python 现代开发学习笔记

(二十二)训练模式、评估模式与梯度开关

# 项目文件:demos/mode_and_grad.py
import torch
from torch import nn

torch.manual_seed(7)
x = torch.ones(8, requires_grad=True)
layer = nn.Dropout(0.5)
layer.train()
print("训练输出", layer(x).tolist())  # 保留项乘 2,丢弃项变为 0。
layer.eval()
output = layer(x)
print("评估输出", output.tolist(), "仍记录梯度", output.requires_grad)
with torch.inference_mode():
    # eval 中的 Dropout 原样交回 x;增加一次计算,观察新结果的梯度记录。
    print("推理记录梯度", (layer(x) * 2).requires_grad)

Dropout(0.5) 在训练模式下随机将一部分项设为零,其余项乘二,使随机处理后的平均量级得到保留。评估模式不再随机丢弃,而是按输入原值通过。完整 CNN 的 Dropout 比例为 0.2。

model.train() 与 model.eval() 递归切换这些层的行为。它们不会自动关闭自动微分,所以例中评估输出仍能参与求导。torch.no_grad() 与 torch.inference_mode() 则控制后续计算是否记录梯度;推理代码把评估模式与推理上下文一起设置。

例中的评估 Dropout 直接交回原张量 x,并没有改变 x 原来的属性;在推理上下文内再乘二,才得到本次不记录梯度的新计算结果。观察“本次做了什么运算”,比只盯着旧张量的标记更容易理解。

同一输入在训练 Dropout 中随机置零并缩放,eval 原样通过;梯度开关另列一条线,推理上下文中的新运算不建立求导图

BatchNorm 也会使用训练与评估模式:训练时读取当前批次统计并更新运行记录,评估时使用已有记录。它的运行均值等数据属于前面介绍的缓冲区,会进入 state_dict。继续扩展网络时,可以按同样方法分别检查层行为和梯度记录。

笔记正文与全部题解 · Ctrl / ⌘ K