一、前言

在训练深度学习模型时,小白最常遇到两个问题:

  • 过拟合:训练集效果很好,测试集一塌糊涂

  • 训练不稳定:loss 波动大,收敛慢甚至不收敛

为了解决这些问题,深度学习中引入了很多经典技巧,其中最常用、也最重要的就是:

  • Dropout(随机失活)

  • Batch Normalization(批量归一化,简称 BN)

二、Dropout:随机失活(防止过拟合)

2.1 Dropout 是什么?

一句话理解 Dropout:

训练时,随机让一部分神经元“休息”,不参与计算

这样可以避免模型过度依赖某些神经元,从而提升泛化能力。

2.2 Dropout 工作原理示意图

2.3 Pytorch 示例

import torch

if __name__ == '__main__':
    input_data = torch.randint(1,10,size=(1,4),dtype=torch.float32)
    linear1 = torch.nn.Linear(4,5)

    # Dropout层,20%概率置0
    dropout = torch.nn.Dropout(p=0.2)

    x = linear1(input_data)
    x = torch.tanh(x)

    # Dropout随机失活:经过Dropout随机失活层以后,输出结果值变成0
    print("随机失活前:", x)
    x = dropout(x)
    print("随机失活后:", x)

输出结果

随机失活前的结果 tensor([[ 0.9984, -0.3029,  0.9982, -0.9457,  0.9999]],grad_fn=<TanhBackward0>)
随机失活后的结果 tensor([[ 0.0000, -0.0000,  1.2477, -1.1821,  1.2499]], grad_fn=<MulBackward0>)

2.4 Dropout 使用建议

✅ 常用位置:

  • 全连接层(Classifier 部分)

⚠  注意:

  • 卷积层一般少用 Dropout

  • Dropout 不会加速训练,只是防过拟合

三、Batch Normalization:批量归一化(加速训练)

3.1 BN的作用

随着网络变深,会出现:

  • 每一层输入分布不断变化

  • 梯度不稳定

  • 学习率不敢调大

BatchNorm 的核心作用:

把每一层的输入“拉回到稳定分布”

3.2 BatchNorm 前后数据分布变化

3.3 BN 的核心流程

核心流程可分为两步:

Step1:标准化(Normalization)
把一个 batch 的特征变成“均值≈0、方差≈1”的分布:

$$ \hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} $$

Step2:再做一次可学习的仿射变换(Affine Transform)

$$ y = \gamma \hat{x} + \beta $$

$\gamma$$\beta$为可学习参数:

$\gamma$(scale):控制“放大/缩小”

$\beta$(shift):控制“平移/偏置”

3.4 Pytorch示例

def demo1():
    # 准备输入的特征数据
    # 1张图片,2个颜色通道,图片高度是3,宽度是4
    input_2d = torch.randn(size=(1,2,3,4))
    print("批量归一化前的数据:",input_2d)

    # 批量归一化处理
    """
        num_features:在处理图片的时候,该值需要与图片的颜色通道保持一致
        eps:小常数,为了避免分母为0
        affine:通常都设置为True,表示神经网络自动去调整γ和β
    """
    # 创建一个二维批归一化层(torch.nn.BatchNorm2d)实例
    # 参数说明:
    #   num_features: 输入特征图的通道数,设置为2表示处理2通道的输入
    #   eps: 用于数值稳定性的小常数,防止除零错误,设置为1e-5
    #   momentum: 动量参数,用于计算运行统计量的动量值,设置为0.1
    #   affine: 布尔值,控制是否使用可学习的仿射变换参数,设置为True表示启用
    # 返回值:
    #   torch.nn.BatchNorm2d对象,用于对2D输入进行批归一化操作
    bn2d = torch.nn.BatchNorm2d(num_features=2,eps=1e-5,momentum=0.1,affine=True)

    output = bn2d(input_2d)

    print(output)
    print(bn2d.weight) # 也就是γ
    print(bn2d.bias) # 也就是β

输出结果:

批量归一化前的数据: tensor([[[[-0.2085,  0.7846, -0.1881, -2.7756],
          [-0.9371,  0.7341, -1.3063, -1.6797],
          [ 0.3303, -0.7707, -0.5810, -0.9489]],

         [[ 0.8032, -0.2420, -0.1430, -0.6692],
          [-0.1647, -0.1789,  0.8901, -1.0401],
          [-1.3928,  0.3604, -0.3477, -0.8258]]]])
tensor([[[[ 0.4288,  1.4415,  0.4495, -2.1893],
          [-0.3143,  1.3900, -0.6908, -1.0716],
          [ 0.9783, -0.1446,  0.0488, -0.3264]],

         [[ 1.5857,  0.0059,  0.1555, -0.6399],
          [ 0.1226,  0.1013,  1.7170, -1.2004],
          [-1.7335,  0.9164, -0.1539, -0.8766]]]],
       grad_fn=<NativeBatchNormBackward0>)
Parameter containing:
tensor([1., 1.], requires_grad=True)
Parameter containing:
tensor([0., 0.], requires_grad=True)

四、Dropout vs BatchNorm 对比总结

对比项 Dropout BatchNorm
主要作用 防止过拟合 稳定训练、加速收敛
是否加速训练
是否正则化 ⚠ 间接
常见位置 全连接层 Conv / Linear 后

更多推荐