前言:为何需要正则化?
在设计和训练机器学习模型,尤其是深度神经网络时,我们最终的目标是希望模型在从未见过的新样本上也能表现出色,这就是模型的泛化能力。然而,神经网络强大的表示能力是一把双刃剑,它在能够完美拟合训练数据的同时,也极易陷入“过拟合”(Overfitting)的陷阱——模型学到了训练数据中的噪声和特有模式,导致在测试集上表现不佳。
为了抑制过拟合,提升模型的泛化能力,研究者们提出了许多策略,这些策略被统称为正则化(Regularization)。本文将深入探讨两种在深度学习中被广泛使用且效果显著的正则化技术:Dropout(随机失活) 和 Batch Normalization(批量归一化)。
一、 Dropout:让神经元“随机休假”的智慧
在训练参数众多的深层神经网络时,如果数据量相对不足,模型很容易过拟合。Dropout 是一种为解决此问题而设计的、简单却异常有效的正则化方法。
1. 什么是 Dropout?
Dropout 的核心思想可以通俗地理解为:在模型的训练过程中,让每个神经元都有一定的概率“临时罢工”。

具体来说,在每次训练迭代中,Dropout 会以一个预设的丢弃概率 p 随机地将一部分神经元的激活值置为 0。这意味着这些神经元在本次前向传播和反向传播中都不会被激活,也不会更新权重。
这个过程相当于我们每次都在训练一个“残缺”的、更小的子网络。由于每次训练的子网络都不同,这能够有效防止神经元之间产生复杂的共适应关系(co-adaptation)。因为每个神经元都不能过分依赖于其他任何特定的神经元,它必须学会提取更鲁棒、更有泛化能力的特征。
2. Dropout 的工作原理
训练阶段 (model.train())
在训练过程中,Dropout 的实现包含两个关键步骤:
💡 为什么要缩放?—— Inverted Dropout 的奥秘
缩放是确保模型在训练和测试时行为一致性的关键。让我们来理清其中的逻辑:
-
原始状态:假设一个神经元的输出是 x,其期望值就是 x。
-
引入 Dropout (未缩放):该神经元有 (1-p) 的概率输出 x,有 p 的概率输出 0。那么它的输出期望值就变为:
E[x_dropout] = (1-p) * x + p * 0 = (1-p) * x
-
问题出现:训练时的期望 (1-p) * x 与测试时的期望 x 不一致!这会导致模型在评估时输出的整体尺度偏小。
-
解决方案:为了弥补这个差距,我们对保留下来的激活值进行“放大”,也就是乘以 1 / (1-p):
E[x_dropout_scaled] = (1-p) * (x / (1-p)) + p * 0 = x
-
完美解决:这样,经过缩放后,训练阶段的输出期望就与测试阶段完全一致了。这种在训练时就提前进行缩放,从而让测试阶段无需任何操作的方法,被称为 Inverted Dropout,也是现代深度学习框架中的标准实现。
测试阶段 (model.eval())
在测试(或推理)阶段,Dropout 不起作用。所有的神经元都会被激活并参与计算。这样做是为了获得一个稳定且确定的预测结果,我们希望利用整个网络学到的所有知识来进行最准确的预测。由于训练时已经进行了缩放,测试时无需做任何额外操作。
3. Dropout 使用建议
- 丢弃率 p 的选择:p 的取值通常在 0.2 到 0.5 之间。
- 对于输入层和靠近输入的隐藏层,p 可以设置得小一些(如 0.1-0.2),因为这些层学习的是基础特征,不希望丢失过多信息。
- 对于隐藏层,尤其是全连接层,p=0.5 是一个常用的经验值。
- 对于非常深的网络,较大的丢弃率(如 0.5 或 0.6)可能更有效。
- 应用位置:通常,Dropout 层被添加在全连接层(激活函数之后)。在卷积网络中,它也可以用在卷积层之后,但更常见于全连接部分。
"""
案例:
代码演示 随机失活.
正则化的作用:
缓解模型的过拟合情况.
正则化的方式:
L1正则化: 权重可以变为0, 相当于: 降维.
L2正则化: 权重可以无限接近0
DropOut: 随机失活, 每批次样本训练时, 随机让一部分神经元死亡, 防止一些特征对结果的影响较大(防止过拟合)
BN(批量归一化): …
"""
# 导包
import torch
import torch.nn as nn
# 1. 定义函数, 演示: 随机失活(DropOut)
def dm01():
# 1. 创建隐藏层输出结果.
t1 = torch.randint(0, 10, size=(1, 4)).float()
print(f't1: {t1}') # t1: tensor([[0., 5., 6., 3.]])
# 2. 进行下一层 加权求和 和 激活函数计算.
# 2.1 创建全连接层(充当线性层)
# 参1: 输入特征维度, 参2: 输出特征维度.
linear1 = nn.Linear(4, 5)
# 2.2 加权求和.
l1 = linear1(t1)
print(f'l1: {l1}')
# 2.3 激活函数.
output = torch.relu(l1)
print(f'output: {output}')
# 3. 对激活值进行随机失活dropout处理 -> 只有训练阶段有, 测试阶段没有.
dropout = nn.Dropout(p=0.5) # 每个神经元都有50%的概率被 kill.
# 具体的 随机失活动作.
d1 = dropout(output)
print(f'd1(随机失活后的数据): {d1}') # 未被失活的进行缩放, 缩放比例为: 1 / (1 – p) = 2
# 2. 测试
if __name__ == '__main__':
dm01()
二、 Batch Normalization:稳定数据分布的“压舱石”
1. 问题的根源:内部协变量偏移 (Internal Covariate Shift)
在神经网络的训练过程中,数据以一个个批次(batch)的形式流经网络。每一层的参数更新都会导致其输出数据分布的变化,而这个输出又作为下一层的输入。因此,对于网络中的深层部分来说,它所接收到的输入数据分布在训练过程中是不断变化的。这种现象被称为内部协变量偏移。
这就使得网络参数需要频繁地进行大的调整以适应流经网络的不同分布的数据,给模型训练带来非常大的不稳定性,使得模型难以收日志,收敛速度变慢。
Batch Normalization (BN) 正是为了解决这个问题而提出的。
2. BN 的工作原理
BN 的核心思想是:在网络的每一层输入前,对数据进行标准化处理,使其分布保持稳定(例如,均值为0,方差为1),然后再进行一次线性变换,以保留模型的表达能力。

BN 的计算过程可以分为两步:
第一步:标准化 对于当前 mini-batch 的数据,计算其均值 E(x) 和方差 Var(x),然后对其进行标准化:
x
^
=
x
−
E
(
x
)
V
a
r
(
x
)
+
ϵ
\\hat{x} = \\frac{x – E(x)}{\\sqrt{Var(x) + \\epsilon}}
x^=Var(x)+ϵ
x−E(x) 其中 ε (eps) 是一个极小的常数(如 1e-5),用于防止分母为 0。
第二步:缩放与平移 标准化的数据虽然分布稳定,但也可能限制了网络的学习能力(例如,将数据强制推入激活函数的线性区域)。为了恢复模型的表达能力,BN 引入了两个可学习的参数:缩放因子 γ (gamma) 和平移因子 β (beta)。
y
=
γ
x
^
+
β
y = \\gamma \\hat{x} + \\beta
y=γx^+β 通过学习 γ 和 β,网络可以自行决定该层数据的最佳分布,甚至可以完全还原出原始的分布(如果 γ = sqrt(Var(x)) 且 β = E(x))。
3. BN 的优势
- 加速训练收敛:通过稳定每层输入的分布,BN 使得梯度更加稳定,允许我们使用更高的学习率,从而大大加快模型的收敛速度。
- 减少内部协方差偏移:这是 BN 的初衷,它让每一层都可以更独立地学习,而不必去适应前序网络层剧烈的参数变化。
- 自带正则化效果:BN 在计算均值和方差时是基于当前 mini-batch 的,这为模型的训练引入了轻微的噪声。这种噪声可以视作一种正则化,有助于提升模型的泛化能力,减少了对 Dropout 等其他正则化技术的依赖。
- 降低对参数初始化的敏感度:BN 使得模型训练对参数初始化的选择不再那么敏感。
4. BN 的训练与测试
BN 在训练和测试阶段的行为同样存在差异:
- 训练阶段 (model.train()):BN 使用当前 mini-batch 的均值和方差进行计算。同时,它会通过**移动平均(moving average)**的方式来维护一个全局的均值和方差,为测试阶段做准备。
- 测试阶段 (model.eval()):在测试时,我们通常一次只处理一个样本,计算批次均值和方差没有意义。因此,BN 会使用在整个训练过程中累积的全局均值和方差来进行标准化。
5. BN 使用建议
- 应用位置:通常,BN 层被添加在卷积层 (Conv2d) 或全连接层 (Linear) 之后,激活函数 (ReLU) 之前。即 Conv/Linear -> BN -> ReLU。
- 应用领域:BN 在计算机视觉领域的各种网络(如 CNNs)中应用极其广泛,效果显著。
"""
案例:
代码演示批量归一化, 它(批量归一化)也属于正则化的一种, 也是用于 缓解模型的 过拟合情况的.
批量归一化:
思路:
先对数据做标准化(会丢失一些信息), 然后再对数据做 缩放(λ, 理解为: w权重) 和 平移(β, 理解为: b偏置), 再找补回一些信息.
应用场景:
批量归一化在计算机视觉领域使用较多.
BatchNorm1d:主要应用于全连接层或处理一维数据的网络,例如文本处理。它接收形状为 (N, num_features) 的张量作为输入。
BatchNorm2d:主要应用于卷积神经网络,处理二维图像数据或特征图。它接收形状为 (N, C, H, W) 的张量作为输入。
BatchNorm3d:主要用于三维卷积神经网络 (3D CNN),处理三维数据,例如视频或医学图像。它接收形状为 (N, C, D, H, W) 的张量作为输入。
"""
# 导包
import torch
import torch.nn as nn
# 1. 定义函数, 处理 二维数据.
def dm01():
# 1. 创建图像样本数据.
# 1张图片, 2个通道, 3行4列(像素点)
input_2d = torch.randn(size=(1, 2, 3, 4))
print(f'input_2d: {input_2d}')
# 2. 创建批量归一化层(BN层)
# 参1: 输入特征数 = 图片的通道数.
# 参2: 噪声值(小常数), 默认为1e-5.
# 参3: 动量值, 用于计算移动平局统计量的 动量值.
# 参4: 表示使用可学习的变换参数(λ, β) 对归一化(标准化)后的数据进行 缩放和平移.
bn2d = nn.BatchNorm2d(num_features=2, eps=1e-5, momentum=0.1, affine=True)
# 3. 对数据进行 批量归一化处理.
output_2d = bn2d(input_2d)
print(f'output_2d: {output_2d}')
# 2. 定义函数, 处理: 一维数据.
def dm02():
# 1. 创建样本数据.
# 2行2列, 2条样本, 每个样本有2个特征
input_1d = torch.randn(size=(2, 2))
print(f'input_1d: {input_1d}')
# 2. 创建线性层.
linear1 = nn.Linear(2, 4)
# 3. 对数据进行 线性变换.
l1 = linear1(input_1d)
print(f'l1: {l1}')
# 4. 创建批量归一化层.
bn1d = nn.BatchNorm1d(num_features=4)
# 5. 对线性处理结果l1 进行 批量归一化处理.
output_1d = bn1d(l1)
print(f'output_1d: {output_1d}')
# 3. 测试
if __name__ == '__main__':
# dm01()
dm02()
三、Dropout vs. Batch Normalization 总结对比
为了更清晰地理解这两种技术的异同,我们通过一个表格进行总结:
| 核心思想 | 在训练时以一定概率随机“丢弃”神经元。 | 对每一层的输入数据按批次进行标准化处理。 |
| 主要解决问题 | 过拟合 (Overfitting) | 内部协变量偏移 (ICS),加速训练。 |
| 正则化方式 | 通过训练不同的子网络,增强模型鲁棒性。 | 通过批次统计引入噪声,起到正则化效果。 |
| 作用位置 | 通常在全连接层之后,激活函数之后。 | 通常在卷积/全连接层之后,激活函数之前。 |
| 训练/测试差异 | 训练时:随机失活并缩放。测试时:所有神经元工作,无操作。 | 训练时:使用批次统计,并更新全局统计。测试时:使用全局统计。 |
| 主要优点 | 强大的正则化能力,有效防止过拟合。 | 加速收敛,稳定训练,允许高学习率,自带正则化。 |
| 注意事项 | p 的选择需要调试;可能会轻微增加训练时间。 | 对小批量 (small batch size) 效果可能不佳;与某些模型可能不兼容。 |
结语
Dropout 和 Batch Normalization 是深度学习工具箱中两款不可或缺的正则化工具。
- Dropout 像一位严格的教练,通过随机让队员“轮休”,迫使每个队员都变得更独立、更强大,从而打造一支整体实力更强的团队(模型)。
- Batch Normalization 则像一个精密的稳定器,它确保了数据在流经深层网络时始终保持“队形整齐”,让整个训练过程更平稳、更高效。
在实际应用中,我们可以根据任务需求和模型特性选择使用其中一种或两种。理解它们的工作原理和差异,将帮助我们更有效地构建和优化深度学习模型,向着更强的泛化能力迈进。
🙏 课程推荐与参考 (Reference)
再次强调,本文核心知识点均提炼自 B 站黑马程序员 的精品课程,老师讲得非常详细,大家一定要去支持!
课程名称: AI大模型《神经网络与深度学习》全套视频课程,涵盖Pytorch深度学习框架、BP神经网络、CNN图像分类算法及RNN文本生成算法



