一个两层全连接网络,训练集准确率 99.8%,验证集 71%。AI 训练时加一行 Dropout,比例 0.5,验证集涨到 78%,训练集掉到 92%。同一份数据、同一个优化器,只多了一个随机置零的动作。这个动作看着像在搞破坏,实际效果是让模型别把训练集背下来。下面讲它压的是什么、有几种变体、代价在哪、什么情况下用了反而更差。
它压的是神经元之间的默契
没有正则的网络上,某些单元会形成固定搭配:A 只在 B 也激活时才有用,两个一起把某几条训练样本记住。这种搭配在训练集上效率极高,换个分布就失效,因为真实数据里不会总按那个组合出现。
Dropout 每步按比例随机把一部分单元置零,只让剩下的参与前向和反向。某个单元这一步被关掉,它的伙伴就没法依赖它;下一步重新随机,搭配又被拆散。反复几十万步之后,网络被迫学出更独立的特征,任何单点缺失都不至于让输出崩掉。
这也是它和正则化里权重衰减那类方法的区别:后者压的是权重的大小,它压的是单元之间的依赖关系。两者作用点不同,可以叠加使用。至于它到底在治什么病,得先看过拟合那篇里训练集与验证集分叉的图。
四种做法,代价各不相同
同为「训练时随机丢」,落到不同结构上,做法和代价差别不小:
| 做法 | 适合谁 | 代价 | 失效条件 |
|---|---|---|---|
| 标准 Dropout | 全连接层、参数远多于样本 | 收敛变慢,同样轮数需要更多步 | 模型本身欠拟合,或数据量已经很充足 |
| Spatial Dropout | 卷积网络、通道存在冗余 | 整通道丢弃,信息损失比逐元素大 | 通道数本来就少,或任务依赖细粒度纹理 |
| DropConnect | 小样本、以全连接为主的结构 | 实现复杂,主流框架不直接支持 | 赶进度用默认配置时 |
| 权重衰减 | 想要稳定、可复现的正则 | 系数要单独调,过大会压住有效容量 | 需要打破特征共适应时,它做不到 |
四行里最常被误用的是第一行。0.5 成了习惯值,但在很深的网络上,这个比例常常偏高,尤其在靠近输出的层,丢一半等于把刚学到的特征直接抹掉。
训练时先除以保留概率,这一步不能省
早期实现里,训练时直接置零,推理时把输出乘上保留概率,让两边的期望对齐。现在框架默认反过来:训练时对被保留的单元除以 1 减 p,推理时什么都不做。
两种写法数学上等价,工程上差很多。前者要求推理代码记得缩放,忘了就整体偏小,输出分布和训练时对不上;后者把缩放放进训练,推理路径和普通网络完全一样,导出、量化、部署都不用改。这也是为什么现在只需要切到推理模式,不必再做额外处理。
「切到推理模式」这句话值得单独记一笔。忘了切,每次推理结果都不一样,同一个输入跑两遍给出两个答案,排查起来极费时间。这类错误在复现实验、做对比评测时最容易发生,也最难被怀疑到。
三种解释,各自成立一部分
防止共适应是最直观的一种:单元不能指望固定伙伴总在,只好学得更独立。集成视角更严格一些:每次丢弃后的网络是一个不同的子网络,训练过程近似在同时训练大量子网络,推理时用完整网络近似它们的平均。这种平均效应和集成学习里多模型投票的道理相通,只是把训练成本压进了一次训练。
噪声视角则把它看成给激活值加了乘性扰动,效果接近数据增强:模型见到的每一版输入都略有不同,自然不容易记住细节。
三种解释各有覆盖不到的地方,但都指向同一个结果——模型对单点扰动的敏感度下降。这也解释了它为什么在参数多、样本少的场景里最有效:那种场景下共适应最容易发生。
模型在训练集上都没学好,它只会更糟
Dropout 治的是过拟合,不是能力不足。训练损失还很高、验证损失也高,说明模型欠拟合,这时候加它等于在本就不够的容量上再砍一刀,两边都会更差。先确认问题是过拟合,再考虑上它。
它也有和其他层打架的时候。卷积网络里它常和批归一化一起出现,两者的方差假设不一致:归一化按批统计,随机丢弃又改变了每步的激活分布,叠在一起容易让训练不稳。实践中的做法是把比例调低,或者只在最后的全连接头部分使用。
推理侧还有一处它管不了:它不改变模型的表达能力上限,也不解决分布漂移。上线半年后输入分布变了,验证集上那点提升会被吃掉,那是数据层面的问题,靠正则补不回来。
比例和时机,比实现细节更影响结果
比例常用 0.2 到 0.5,但这个区间不是随手取的。层越宽、参数量越大,能承受的丢弃比例越高;靠近输出的层丢得太多,等于把刚学到的特征抹掉。经验做法是输入侧低一些,中间全连接层高一些,输出前一层再降回来。
时机上,它通常在训练中段之后才显出价值。一开始就开高比例,模型连基本模式都没学到,收敛会明显变慢。有些训练脚本按轮次线性提高比例,前期让模型先学,后期再加约束。
判断该不该用,看两条曲线的差距就够了:差距在扩大,轮到它上场;两条都低,说明该加容量或加数据。这个判断比调比例重要得多,也是最容易被搞反的次序。
速查:上 Dropout 之前先确认四件事
- 训练集是不是已经学得很好,欠拟合就别加
- 比例是否按层区分,别整网统一设成 0.5
- 推理代码有没有切到推理模式
- 和批归一化叠在一起时,比例有没有调低


