返回专辑
·Johan·4 分钟阅读

Dropout:推理要关掉

Dropout 训练时随机丢弃激活、推理时必须 eval 关闭——train mode 部署会让输出随机抖动,和 BatchNorm 一样要 model.eval()。

Dropout:推理要关掉

1. 部署输出随机抖,常是 Dropout 没关

分类服务同一输入连续两次推理结果不同——查代码发现 export 前忘了 model.eval(),Dropout 仍在 train mode 随机 zero 神经元。和 BatchNorm 一样,Dropout 的行为由 train/eval 模式决定;部署必须 eval,否则输出是随机的。

2. 训练时做什么

nn.Dropout(p=0.5) 训练时以概率 将激活置零,其余激活按 scale(inverted dropout,PyTorch 默认)——保证 train 和 eval 期望一致。推理时 model.eval() 关闭 Dropout,所有激活保留,不再 scale。

python
class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(256, 128)
        self.drop = nn.Dropout(0.5)
        self.fc2 = nn.Linear(128, 10)
    def forward(self, x):
        return self.fc2(self.drop(F.relu(self.fc1(x))))

model.train()   # Dropout 生效
model.eval()    # Dropout 关闭

Transformer 里 attention dropout、FFN dropout 同理——eval 时全部关闭。torch.no_grad() 只关梯度,不切换 Dropout;必须显式 model.eval()

3. p 的选择与位置

是 MLP 常见默认;CNN 全连接层前常用 0.5;Transformer FFN 常用 0.1–0.2。过大 欠拟合;过小正则弱。Dropout 放在全连接层前、embedding 后;卷积层用 Dropout2d 对 spatial 维度 drop。

小数据过拟合可增大 ;大数据或已有强正则可减小或不用 Dropout。BatchNorm 与 Dropout 同层顺序有争议——实践中 BN 在前 Dropout 在后较常见。

4. 导出与 TorchScript/ONNX

torch.jit.trace 或 ONNX export 时必须在 eval mode 下 trace,否则 graph 可能固化 train 行为或 export 后行为不一致。CI 加测试:同一 input 连续 forward 两次,output 应 identical(eval mode 下)。

model.train() accidentally 在 validation loop 里也会打开 Dropout——val metric 会带噪声,且与 deploy 不一致。val 和 test 循环开头写 model.eval(),train 循环写 model.train()

5. 与 MC Dropout 的区分

Monte Carlo Dropout 故意在推理时保持 Dropout 开,多次 forward 估 uncertainty——这是有意的 eval-time dropout,与部署 bug 不同。生产 serving 默认仍应 eval 关 Dropout;uncertainty 需求单独设计 inference 路径。

6. 案例:验证集指标虚高

某模型验证准确率比测试高两个点——发现验证循环里误调 model.train(),Dropout 随机性污染 val。改 eval 后 val 与 test 对齐。train/eval 切换是 metric 可信的前提。

7. 验收

  • 部署前 model.eval();同一 input 多次 inference 结果一致。
  • val/test loop 不用 train mode。
  • export(ONNX/TorchScript)在 eval 下完成。
  • CI 含 eval mode 确定性测试。
  • 文档写明 inference 必须 eval,与 BN 一并检查。

8. 落地与衔接

推理服务启动脚本在加载权重后强制切换到评估模式,并在健康检查里对固定输入连跑两次断言输出一致。导出中间表示或部署格式时必须在评估模式下追踪,与 eager 模式数值对比。验证循环模板默认评估模式,训练循环开头再切回训练模式,避免复制粘贴漏切换。文档把随机失活与批归一化并列为部署必查项,新人清单勾选后再上线。代码审查时专门看一眼验证循环是否误开训练模式。

9. 案例复盘

某分类服务客户报同一图片两次结果不同,追踪发现封装里只包了无梯度未切评估模式。修改后输出稳定,持续集成新增评估模式确定性测试防回归。另一次验证集虚高两点的根因是验证循环误开训练模式,随机失活污染指标。现在指标脚本与推理服务共用同一评估封装,训练与评估切换不再靠记忆。该问题在多个项目重复出现,已写入常见故障手册。

Dropout 是训练正则,不是推理特性。忘了 eval,模型在部署里仍是「随机」的——这是最常见也最容易修的部署 bug 之一。把 eval 确定性与 BN 检查绑在同一 preflight,比单独文档提醒更不容易漏。发版前用固定输入做两次推理对比,应成为标准冒烟步骤。验证与推理共用评估封装后,训练循环仍须在每轮开头显式切回训练模式。服务监控可加入固定探针请求比对输出哈希,发现非确定性立即告警并回滚。

← 全部文章

johan's blog