为什么Dropout能防止过拟合:隐式集成学习解释
Dropout 的操作只有一句话:训练时按概率把一部分神经元输出置零。它防止过拟合的数学核心,是训练大量共享权重的子网络,并在测试时用完整网络近似平均它们的预测。
1. 拆开Dropout的训练动作
-
设定保留概率 $q$,丢弃概率 $1-q$。例如框架
nn.Dropout(p=0.5)中p=0.5表示丢弃概率,保留概率 $q=0.5$。每个神经元独立生成掩码 $m_i \sim \mathrm{Bernoulli}(q)$,$m_i=1$ 表示保留,$m_i=0$ 表示丢弃。 -
采样每个 mini-batch 重新采样掩码。同一套权重在不同 batch 中经历的存活神经元组合不同。
-
计算训练输出。采用 inverted dropout 时,训练输出为 $h_i' = \frac{m_i}{q} h_i$。保留的神经元被放大 $1/q$ 倍,抵消丢弃带来的期望下降。
-
更新共享权重。反向传播只经过保留的神经元,每个采样到的子网络贡献一次梯度。
-
关闭测试阶段的随机丢弃。测试时使用完整网络,并且不再缩放。因为训练时已经除以 $q$,测试输出与训练时随机输出的期望一致。
对固定输入,单个神经元输出的期望满足 $\mathbb{E}[h_i'] = h_i$。所以测试时使用完整网络,相当于让随机子网络的期望预测成为最终预测。
2. 数出到底有多少个子网络
如果一层有 $n$ 个神经元,每个神经元都有保留和丢弃两种状态,那么这一层共有 $2^n$ 种掩码。整个网络包含多层时,总子网络数量是各层数量的乘积,远远超过显式训练多个模型的数量。
每个子网络都是原网络删掉部分神经元后的版本,但它们共享同一套权重。训练过程不是分别训练每个子网络,而是每次只训练一个随机子网络,并更新共享权重。共享权重让不同子网络互相影响、互相约束。
这种约束的直接效果是抑制共同适应。共同适应是指某个神经元学会依赖另一个特定神经元一定存在。Dropout 让伙伴神经元随时可能消失,模型就不能把预测压在脆弱的组合上,而必须学习更独立、更冗余的特征。
3. 平均为什么能降低过拟合
设单个子网络的预测误差方差为 $\sigma^2$,子网络之间的平均相关性为 $\rho$,平均 $M$ 个子网络的预测方差为:
$$ \mathrm{Var}(\bar f) = \rho \sigma^2 + \frac{1-\rho}{M}\sigma^2 $$
当 $M$ 很大时,第二项趋近于 0。即使子网络之间相关性 $\rho$ 不为零,平均也能降低方差。Dropout 测试时不是显式计算所有子网络,而是用完整网络近似这个平均。完整网络相当于一个参数共享的隐式集成模型。
单个模型容易记住训练集里的噪声。多个子网络平均后,噪声方向不一致,互相抵消;真实信号方向一致,被保留下来。这就是隐式集成学习解释。
4. 线性情形下推导测试缩放
只看一个线性输出单元,输入为 $x$,权重为 $w$。训练时掩码为 $m_i$,inverted dropout 输出为:
$$ y' = \sum_i \frac{m_i}{q} w_i x_i $$
对掩码求期望:
$$ \mathbb{E}[y'] = \sum_i \frac{\mathbb{E}[m_i]}{q} w_i x_i = \sum_i w_i x_i $$
期望等于完整网络输出。测试时直接使用完整网络,就是让随机子网络的期望预测成为最终预测。
非线性网络中,期望与非线性函数不能精确交换,所以完整网络只是近似平均。但缩放规则仍然有效,因为它保持每层激活值的均值大致不变。
5. 从正则角度看Dropout
Dropout 给神经元输出加乘性噪声。模型不能把权重压在一个特征上,因为该特征随时可能被置零。对线性回归,这种噪声会诱导类似 L2 正则的效果。L2 正则可以理解为让权重不要过大的惩罚项。
更通俗地说,模型被迫学习冗余表示:多个特征都能支持同一结论。冗余表示对训练噪声不敏感,因此泛化更好。
6. 实操检查清单
-
选择丢弃率。全连接层常用丢弃概率
0.5,输入层常用0.1到0.2,卷积层常用0.1到0.3。框架参数通常是丢弃概率,nn.Dropout(p=0.5)表示丢弃概率0.5。 -
放置Dropout。常见位置是全连接层之后、激活函数之后;卷积网络常在池化后或全连接前。不要放在输出层。
-
切换训练和评估模式。训练前 调用
model.train(),推理前 调用model.eval()。忘记切换会让推理带随机性。 -
确认缩放方式。使用 inverted dropout,即训练时除以保留概率,测试时不缩放。多数现代框架默认这样做。
-
监控训练损失和验证损失。训练损失持续下降而验证损失上升时,增大丢弃率或 加入早停。
-
调整容量。如果丢弃率过高,训练损失也下不去,说明模型欠拟合,降低丢弃率。
import torch
import torch.nn as nn
model = nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(256, 10)
)
model.train()
# 训练循环
model.eval()
# 推理循环
7. 避免常见误区
-
不要在测试时继续随机丢弃。测试需要确定性,随机丢弃会引入噪声。
-
不要把子网络看成完全独立模型。它们共享权重,相关性很高,所以 Dropout 的集成不是标准袋装集成。
-
不要认为丢弃率越高越好。丢弃率太高会丢失信息,导致欠拟合。
-
不要忽略批量归一化等层的模式切换。
model.eval()不仅关闭 Dropout,还会切换批量归一化统计量。 -
不要用 Dropout 替代数据增强和其他正则化。它是工具箱中的一件,不是万能药。
Dropout 防止过拟合的机制是:训练时随机采样大量共享权重的子网络,迫使每个神经元不依赖特定伙伴;测试时用完整网络近似这些子网络预测的平均,从而降低方差、抑制噪声记忆。

暂无评论,快来抢沙发吧!