dropout层在预测阶段未调用model.eval()会导致输出波动,因其仍按训练逻辑随机丢弃神经元;其行为由self.training标志控制,true时置零缩放,false时直通;f.dropout需显式传training=false,dataparallel/ddp需对module调eval()。

Dropout层在预测阶段不调用model.eval(),结果必然波动——它不是“失效”,而是按训练逻辑继续随机丢弃。
Dropout行为完全由self.training标志控制
PyTorch的nn.Dropout本身不保存状态,它只在self.training == True时执行随机置零+缩放;否则直接返回输入(无任何计算)。这个判断来自模型顶层的training属性,并递归影响所有子模块。
- 训练循环中漏写
model.train()→ Dropout全程透明,正则化失效 - 验证/预测前没调
model.eval()→ Dropout仍每轮随机丢一半,相同输入输出不同 - 手动设
model.training = False虽可跳过Dropout,但不会同步冻结BatchNorm的running_mean/running_var,不推荐
F.dropout函数不自动读取模型状态,必须显式传参
如果你在forward里用了torch.nn.functional.dropout(比如自定义层或动态Dropout),它和nn.Dropout不同:不感知model.training,必须手动加training=False。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 错误写法:
F.dropout(x, p=0.5)—— 即使在model.eval()下也随机丢弃 - 正确写法:
F.dropout(x, p=0.5, training=False) - 注意:
training参数类型是bool,不能传None或省略
模型被DataParallel或DistributedDataParallel包装时,eval()要作用到内层
直接对包装后的模型调model.eval(),只会设置包装器自身的training标志,底层真实模型仍处于train模式。
- 检查方式:
print(model.training)为False,但print(model.module.training)可能仍是True - 正确做法:用
model.module.eval()(单机多卡)或model.module.eval()(DDP) - 若不确定是否被包装,可统一用
getattr(model, 'module', model).eval()
真正稳定的预测,不止靠model.eval()——Dropout只是表象,背后还连着BatchNorm统计量、cuDNN算法、数据加载顺序、随机种子四个强依赖项。少锁一个,波动就藏在你以为“已经搞定”的地方。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










