✨ 复制成功!

以文会友,打造好学人设!

📋 已复制到剪贴板:

Dropout如何防止过拟合?它在训练和推理阶段的差异是什么?

创建时间:2026-08-29 更新时间:2026-08-29 阅读次数:1008 次

Dropout如何防止过拟合?它在训练和推理阶段的差异是什么?

Dropout 是深度学习中最经典、最有效的正则化技术之一。它的核心思想非常巧妙:在训练时随机"丢弃"一部分神经元,迫使网络不过度依赖某些特定的神经元组合,从而学习到更鲁棒、更通用的特征。

一、Dropout 如何防止过拟合?

要理解 Dropout 的正则化效果,可以从以下几个角度来剖析:

1. 打破"协同适应"

这是 Dropout 最直观的动机(来自 Hinton 的原始论文)。

在标准的全连接网络中,神经元之间可能会形成一种"共谋"关系:某个神经元专门负责修正另一个神经元的错误,两者高度依赖,只对训练集有效,对测试集无效。

引入 Dropout 后,每次前向传播都相当于从一个大的网络中随机采样出一个子网络。由于每个神经元在训练时都有可能被随机丢掉,它们就不能依赖特定的"搭档",而必须学会独立地从输入中提取有用的特征。这迫使每个神经元都变得更"全能"。

2. 隐式的模型集成

这是目前解释 Dropout 效果最主流的理论视角。

假设网络有 $n$ 个神经元,加上 Dropout 后,每一次训练迭代实际上都在训练一个不同的、更稀疏的子网络(相当于训练了 $2^n$ 个可能的子模型)。

  • 推理阶段:Dropout 被关闭,使用所有的神经元。
  • 效果:最终的预测相当于对所有子网络预测结果的一种几何平均(在权重缩放后近似)。这类似于 Bagging(如随机森林)的思想——集成多个模型通常比单个模型具有更好的泛化能力。

3. 增加噪声,提升鲁棒性

Dropout 可以看作是一种在特征层面注入乘性噪声的方式。每次训练时,输入经过该层后,某些值会被强制设为 0。

这迫使网络学会如何在信息不完整、有缺失的情况下仍然做出正确的判断,从而提高模型的鲁棒性。这类似于数据增强,只不过 Dropout 是在特征空间(隐层)而不是输入空间做增强。

二、训练与推理阶段的差异

这是使用 Dropout 时最容易出错、也最需要理解的地方。Dropout 是一种只在训练阶段激活的技术。

阶段 Dropout 状态 操作 目的
训练阶段 开启 以概率 $p$ 随机将神经元输出设为 0;剩余神经元的输出除以 $(1-p)$(详见下文缩放规则)。 随机采样子网络,注入噪声,强制学习鲁棒特征,防止过拟合。
推理/测试阶段 关闭 所有神经元都参与计算,不需要随机丢弃,也不需要缩放。 使用完整的训练好的网络,利用所有特征进行预测,保证结果的确定性和精度。

关键差异详解:两种缩放规则

在推理时,我们必须对权重进行缩放(Scale),以弥补训练时部分神经元被丢弃导致的输出期望变化。业界通常有两种实现方式,不能混淆

  1. Inverted Dropout(反向 Dropout)—— PyTorch/TensorFlow 的默认实现
  2. 训练时:随机丢掉 $p$ 比例的神经元(置 0),剩余的神经元输出值除以 $(1-p)$
  3. 推理时:什么都不做,直接使用完整网络。
  4. 原因:训练时由于做了除以 $(1-p)$,使得该层输出的总体期望值(Magnitude)与没有 Dropout 时保持一致。因此,推理时无需任何额外操作,权重可以直接复用。

  5. Vanilla Dropout(原始实现)

  6. 训练时:随机丢掉 $p$ 比例的神经元,剩余神经元不做缩放
  7. 推理时:所有神经元的权重乘以 $(1-p)$
  8. 原因:因为训练时输出变小了,推理时要用全部神经元,所以要把权重调小,以保证输入到下一层的数值尺度一致。

总结:现代框架(如 PyTorch 的 nn.Dropout)默认使用 Inverted Dropout。因此,你只需在模型定义中加上 Dropout 层,框架会自动处理训练和推理的切换,不需要model.eval() 时手动修改权重。

三、代码演示(PyTorch)

在 PyTorch 中,切换模式由 model.train()model.eval() 控制。

import torch
import torch.nn as nn

# 定义:丢弃概率为 50%(p=0.5)
dropout = nn.Dropout(p=0.5)

# 输入示例
x = torch.ones(10)  # 全 1 向量

# 1. 训练阶段(默认是 train 模式)
dropout.train()
y_train = dropout(x)
print("训练阶段输出:\n", y_train)
# 预期现象:
# 一部分值变为 0(被丢弃),
# 另一部分值变为 2(因为 Inverted Dropout 除以了 1-p=0.5)

# 2. 推理阶段(切换为 eval 模式)
dropout.eval()
y_eval = dropout(x)
print("推理阶段输出:\n", y_eval)
# 预期现象:
# 输出全部为原来的 1,不做任何改变

四、实践注意事项

  1. 放置位置
  2. 通常放在激活函数之后(例如 ReLU -> Dropout)。
  3. 一般用于全连接层。在卷积层后使用 Dropout 的效果通常不好(因为卷积具有空间局部性,丢单个像素点意义不大),如果要在 CNN 中用,可以考虑 SpatialDropoutDropBlock
  4. Transformer 架构(如 BERT、GPT)中,Dropout 被广泛应用于注意力权重、残差连接和 FFN 层。

  5. 概率 $p$ 的选择

  6. 全连接层:常用 $p=0.5$(即保留一半)。
  7. 输入层:通常用较小的 $p$(如 $0.1$ 或 $0.2$),因为原始输入信息最宝贵,不宜过度丢弃。
  8. Transformer:通常用 $p=0.1$。
  9. 大模型欠拟合时:如果模型本身还不够拟合训练集(欠拟合),建议先调小 Dropout(如 0.1)或不使用;如果是过拟合,再调大。

  10. 训练时间: Dropout 会导致网络收敛变慢(因为每次只更新了部分神经元,且噪声大)。通常需要增加 epoch 数来弥补。


📌 面试天下网:一款服务于大一新生的口袋书,让大家在无聊的公共课上可以学习大模型技术!
📌 网站公告:人人都需要的干眼克星上线啦>>>>>>
📌 网站公告:程序出海:中国程序员当下最大的机遇>>>>>>
📌 网站公告:程序员都应该掌握的快速学习法>>>>>>

评论专区

评论加载中...