标准回答
Dropout 是一种正则化方法,训练时随机让一部分神经元失活,迫使网络不过度依赖个别神经元,从而缓解过拟合。现代实现采用「反向 Dropout(inverted dropout)」:训练阶段以保留概率 p 生成 0/1 掩码置零部分激活,并把保留下来的激活乘以 1/p 来补偿被丢弃部分、保持输出期望不变;这样推理阶段就可以直接恒等输出,无需任何缩放,工程上更简洁。下面用 NumPy 实现:
import numpy as np
def dropout(x, p=0.5, training=True, rng=None):
# p: 保留概率(keep prob)。训练随机置零并按 1/p 缩放
if not training or p >= 1.0:
return x # 推理:恒等输出
rng = rng or np.random.default_rng(0)
mask = (rng.random(x.shape) < p).astype(x.dtype) # 保留位为 1
return x * mask / p # 反向 Dropout:缩放 1/p
if __name__ == '__main__':
rng = np.random.default_rng(0)
x = np.ones((4, 5))
y = dropout(x, p=0.5, training=True, rng=rng)
print(y) # 约一半元素为 0,其余为 2.0
# 期望保持不变:训练输出均值 ~ 推理(全 1)的均值
print(y.mean().round(2)) # 接近 1.0常见误区
⚠️ 常见踩坑
混淆 p 是「保留概率」还是「丢弃概率」会导致缩放因子写反(PyTorch 的 p 是丢弃概率,缩放为 1/(1−p));推理阶段误加缩放或继续丢弃会使输出尺度错误。
追问
追问 1:为什么要除以 p(反向 Dropout)?不除会怎样?
不缩放时训练输出的期望是推理的 p 倍,训推分布不一致。早期做法是推理时把权重乘以 p 来对齐,但需要在推理多做一步。反向 Dropout 把补偿放到训练阶段(乘 1/p),让推理保持恒等、零开销,是当前主流实现。
追问 2:Dropout 和 BatchNorm 一起用要注意什么?
两者叠加可能因方差偏移相互干扰,实践中常见做法是减少同时使用,或把 Dropout 放在 BN 之后;很多 CNN 直接用 BN 而省略 Dropout。此外 Transformer 中 Dropout 常用在注意力权重和残差分支上,需谨慎调比例。
延伸学习
与本题相关的知识库文章、术语、工具与行业资讯。
🛠️ AI 工具
- Pytorch
Meta 开源的深度学习框架,100K+ stars。以动态计算图和 Pythonic 风格著称,在学术界和工业界都有广泛应用,支持分布式训练、移动端部署和 ONNX 导出