1. 学习率衰减优化方法

1.1 为什么要进行学习率优化

在训练神经网络时, 一般情况下学习率都会随着训练而变化. 这主要是由于, 在神经网络训练的后期, 如果学习率过高, 会造成loss的振荡, 但是如果学习率减小的过慢, 又会造成收敛变慢的情况.

如下图可以看出: 采用较小的学习率, 梯度下降的速度慢; 采用较大的学习率, 梯度下降太快越过了最小值点, 导致震荡, 甚至不收敛(梯度爆炸).

在这里插入图片描述

1.2 等间隔学习率衰减

在这里插入图片描述
等间隔学习率衰减就是按照固定的批次数进行学习率衰减, 如上图, 每间隔50(step_size)衰减一次.

optim.lr_scheduler.StepLR(optimizer=optimizer, step_size=50, gamma=0.5)
# milestones -> 每次衰减之间的批次间隔数.
# gamma -> 衰减系数.
# 原理 -> lr = lr * gamma.

1.3 指定间隔学习率衰减

在这里插入图片描述
指定间隔学习率衰减就是按照提供的调整轮次来进行学习率衰减.

optim.lr_scheduler.MultiStepLR(optimizer=optimizer, milestones=[50, 125, 160], gamma=0.1, last_epoch=-1)
# milestones -> 设定调整轮次.
# gamma -> 调整系数.
# last_epoch -> 将当前轮次假设成第几个轮次, 如last_epoch=-1(默认值)当前轮次为第0轮, 50轮后进行衰减, 若last_epoch=49则下一轮(50)就开始学习率衰减.
# 原理 -> lr = lr * gamma

1.4 指数学习率衰减

在这里插入图片描述

optim.lr_scheduler.ExponentialLR(optimizer=optimizer, gamma=0.9)
# gamma -> 调整系数, 指数的低.
# 原理 -> lr = lr * gamma ^ epoch.

1.5 小结

方法 等间隔学习率衰减 (Step Decay) 指定间隔学习率衰减 (Exponential Decay) 指数学习率衰减 (Exponential Moving Average Decay)
衰减方式 固定步长衰减 指定步长衰减 平滑指数衰减,历史平均考虑
实现难度 简单易实现 相对简单,容易调整 需要额外历史计算,较复杂
适用场景 大型数据集、较为简单的任务 对训练平稳性要求较高的任务 高精度训练,避免过快收敛
优点 直观,易于调试,适用于大批量数据 易于调试,稳定训练过程 平滑且考虑历史更新,收敛稳定性较强
缺点 学习率变化较大,可能跳过最优点 在某些情况下可能衰减过快,导致优化提前停滞 超参数调节较为复杂,可能需要更多的计算资源

2. 正则化方法

2.1 什么是正则化

在深度学习中, 正则化是一种关键的技术, 用于防止模型过拟合, 从而提高模型的泛化能力.

2.2 Dropout

在训练深层神经网络时, 由于模型参数较多, 在数据量不足的情况下, 很容易过拟合, Dropout(随机失活)是一个简单有效的正则化方法.
在这里插入图片描述

  • 在训练过程中, Dropout的实现是让神经元以超参数p(丢弃概率)的概率停止工作或者激活值被置为0, 未被置为0的进行缩放, 缩放比例为1/(1-p)
  • 实际应用中, Dropout参数p的概率通常取值在0.2到0.5之间.
    • 对于较小的模型或较复杂的任务, 丢弃率可以选择0.3或更小.
    • 对于非常深度网络, 也可以选择较大的值(0.5或0.6).
    • 实际应用中, 通常会在全连接层(激活函数之后)后添加Dropout层(通俗理解dropout要令神经元死亡, 当然要在神经元创建完成之后进行).
      • linear -> relu -> dropout
  • 在测试过程中, 随机失活不起作用
    • 在此时阶段, 使用所有的神经元进行预测, 以获得更稳定的结果.
    • 直接使用训练好的模型进行测试, 由于所有的神经元都参与计算, 输出的期望值会比训练阶段高. 测试阶段的期望输出是 E[x_test] = x.
    • 测试/推理模式: model.eval()
  • 缩放的必要性
    • 在训练阶段, 将参与计算的神经元的输出除以(1-p).
    • 经过Dropout后的期望输出变为 E[x_dropout] = [(1-p) * x] / (1-p) = x, 与测试阶段的期望输出一致.
    • 训练模型: model.train().
# 初始化随机失活层.
dropout = nn.Dropout(p=0.4)
# 初始化输入数据: 表示抹一层的weight信息.
inputs = torch.randint(0, 10, size=[1, 4]).float()
layer = nn.Linear(4, 5)  # 定义一个线性函数.
y = layer(inputs)
y = torch.relu(y)
# 输出未失活FC层的输出结果.
print(y)  # tensor([[0.0000, 1.8033, 1.4608, 4.5189, 6.9116]])
# 输出失活后FC层的输出结果.
print(dropout(y))  # tensor([[0.0000,  3.0055,  2.4346,  7.5315, 11.5193]])

2.3 批标准化

在神经网络的训练过程中, 神经网络的数据都是一个batch, 每个batch之间的数据分布变化非常剧烈, 这就使得网络参数频繁的进行大的调整以适应流经网络的不同分布的数据, 给模型训练带来非常大的不稳定性,使得模型难以收敛。如果我们对每一个batch的数据进行标准化之后,数据分布就变得稳定,参数的梯度变化也变得稳定,有助于加快模型的收敛。
通过标准化每一层的输入,使其均值接近0,方差接近1,从而加速训练并提高泛化能力。
先对数据标准化,再对数据重构(缩放+平移),写成公式如下所示:
在这里插入图片描述

  • λ和β 可学习的参数,它相当于对标准化后的值做了一个线性变换λ为系数,β为偏置;
  • eps 通常指为1e-5,避免分母 0;
  • E(x) 表示变量的均值;
  • Var(x) 表示变量的方差;
    批标准化的使用步骤:
  1. 在网络层后添加添加BN层:
    • 通常,BN层会添加在卷积层 (Conv2d) 或全连接层 (Linear) 之后,激活函数之前。
    • 例如:Conv2d -> BN -> ReLU 或者 Linear -> BN -> ReLU。
  2. 训练时: model.train()
    • BN 层会计算当前批次的均值μ和方差σ²。
    • 然后,利用这两个统计量对当前批次的数据进行规范化。
    • 规范化后的数据会被缩放γ和平移β。
    • 同时,BN层还会维护一个全局均值全局方差的移动平均值,用于推理阶段。
  3. 推理时: model.eval()
    • 推理时,不会再使用当前批次的均值和方差,而是使用训练阶段计算的全局均值全局方差
    • 同样,规范化后的数据会被缩放γ和平移β。
bn1 = nn.BatchNorm1d(num_features=5, eps=1e-5, momentum=0.1, affine=True)
# BatchNorm1d: 二维数据集
# num_features: 和线性计算的输出维度一致
# eps: 小常数
# momentum: 计算均值时使用移动加权平均, 系数, 默认0.1
# affine: 是否使用可学习参数, 默认True
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐