带你从入门到精通——深度学习(六. 神经网络的优化方法和正则化方法)
其中,EMAt是时间t时的指数移动平均值,xt是时间t时的实际值,β被称为平滑因子,取值范围为0<β<1,EMAt−1是值前一时刻的指数移动平均值,初始条件通常为。(缩放+平移),γ和β都是可学习的参数,它相当于对标准化后的数据做了一个线性变换,γ为系数,β为偏置,eps是一个极小的数,以避免分母为0。,鞍点是指函数在此点一阶导数为零,但该点是某一方向上的函数极大值点,在另一方向上是函数极小值点
建议先阅读我之前的深度学习博客,掌握一定的深度学习前置知识后再阅读本文,链接如下:
带你从入门到精通——深度学习(一. 深度学习简介和PyTorch入门)-CSDN博客
带你从入门到精通——深度学习(二. PyTorch中的类型转换、运算和索引)-CSDN博客
带你从入门到精通——深度学习(三. PyTorch中张量的形状重塑、拼接和自动微分)-CSDN博客
带你从入门到精通——深度学习(四. 神经网络的概念、激活函数和参数初始化)-CSDN博客
带你从入门到精通——深度学习(五. 神经网络的搭建、损失函数和反向传播)-CSDN博客
目录
六. 神经网络的优化方法和正则化
6.1 梯度下降算法的优化方法
6.1.1 传统梯度下降算法的缺点
在使用梯度下降算法更新参数时,可能会出现以下情况: 碰到平缓区域,梯度值较小,参数优化变慢;碰到鞍点(saddle point),鞍点是指函数在此点一阶导数为零,但该点是某一方向上的函数极大值点,在另一方向上是函数极小值点,下图中坐标为(0,0)红点即为函数
的一个鞍点:

而鞍点的梯度为0,参数无法优化;最后一种情况是碰到局部最小值,没有找到全局最小值,参数不是最优。

6.1.2 指数移动加权平均
指数移动加权平均(Exponential Moving Average,EMA)是通过对时间序列中的每个数据点进行加权求和得到的,其中最近的数据点具有较高的权重,而较远的数据点权重逐渐减小。这种权重分配是通过一个衰减因子β来实现的,具体的计算公式如下:
![]()
其中,EMAt是时间t时的指数移动平均值,xt是时间t时的实际值,β被称为平滑因子,取值范围为0 < β < 1,EMAt − 1是值前一时刻的指数移动平均值,初始条件通常为
。
注意:EMA的递归公式可以展开为:

6.1.3 动量法
动量法(Momentum)通过累积梯度的历史信息,从而加速收敛并减少震荡,具体来说,动量算法不仅考虑了当前的梯度,还考虑了之前梯度的累积效应,动量法的具体计算公式和参数更新公式如下:
![]()
![]()
vt是累计的历史梯度的指数移动加权平均值,gt为当前梯度值,β为权重系数。
动量法的优势如下:
1. 当参数处于鞍点或者局部极小值的位置时,虽然当前的梯度值为0,但由于动量法已经在先前积累了一些梯度值,使得动量法能够有更大的可能使得跨过鞍点或者局部极小值点。
2. 在梯度值较小的平缓区域时,同样由于梯度的累积效应,动量法也会在该区域可能拥有更大的梯度值,因此有着更快的收敛速度。
3. mini-batch随机梯度下降算法中,每次选取少数的样本梯度确定前进方向,因此可能会出现极小值附近震荡的现象,而动量法使用了指数移动加权平均,平滑了梯度的变化,使得前进方向更加平缓,能够有效地避免出现震荡现象。

在PyTorch中,动量法使用torch.optim.SGD(param,lr,momentum)实现。
6.1.4 Adagrad算法
Adagrad算法的思想是对不同的参数使用不同的学习率进行参数更新,而学习率的总体趋势是逐渐减小,AdaGrad算法的参数更新公式如下:

其中,s为累积平方梯度s = s + g ⊙ g,⊙表示求哈达玛积,g为梯度,a为学习率,
为一个极小的参数,用于防止分母为零。
Adagrad的缺点是可能会使得学习率过早地过量降低,导致模型训练后期学习率太小,较难找到最优解。
在PyTorch中,Adagrad算法使用torch.optim.Adagrad(param,lr)实现。
6.1.5 RMSProp算法
RMSProp算法是对Adagrad算法的优化,最主要的不同是,RMSProp算法使用指数移动加权平均梯度平方替换Adagrad算法中的对梯度平方的直接累加。
RMSProp算法的参数更新公式如下:

其中,s为累积平方梯度
,g为梯度,a为学习率,
为一个极小的参数,用于防止分母为零。
在PyTorch中,RMSProp算法使用torch.optim.RMSprop(param,lr,alpha)实现,alpha即为上述公式中的β。
6.1.6 Adam算法
Adam算法(Adaptive Moment Estimation,自适应矩估计),将动量法和RMSProp算法结合在一起,使用动量法修正梯度的同时,使用RMSProp算法修正学习率,
在PyTorch中,Adam算法使用torch.optim.Adam(param,lr,betas)实现,其中betas传入一个列表,列表中第一个参数为修正梯度的β1,第二个参数为修正学习率的β2。
6.2 学习率优化方法
6.2.1 等间隔学习率衰减法
在PyTorch中,等间隔学习率衰减法通过torch.optim.lr_scheduler.StepLR(optimizer, step_size,gamma=0.1)实现,其中step_size为调整间隔数,gamma为调整系数=0.5,具体的调整方式为:,当step_size=50,gamma=0.5时,lr的变化曲线如下:

6.2.2 指定间隔学习率衰减法
在PyTorch中,指定间隔学习率衰减法通过torch.optim.MultiStepLR(optimizer,milestones, gamma=0.1),其中milestones用于设定调整轮次,当训练轮次等于列表中的轮次数时学习率进行衰减,gamma为调整系数=0.5,具体的调整方式为:,当milestones=[50, 125, 160],gamma=0.5时,lr的变化曲线如下:

6.2.3 指数学习率衰减法
在PyTorch中,指定间隔学习率衰减法通过torch.optim.ExponentialLR(optimizer, gamma),其中gamma为底数,调整方式为:,这里的
为初始学习率,当gamma=0.95时,lr的变化曲线如下:

6.3 正则化方法
在机器学习中,能够减小测试误差、提高模型在新样本上的泛化能力的策略被统称为正则化。神经网络的强大的表示能力经常出现过拟合现象,因此需要使用不同形式的正则化策略。
6.3.1 Dropout
Dropout(随机失活)是一个简单而有效的正则化方法。
Dropout在训练阶段和推理阶段有不同的表现:
在训练阶段,Dropout会让神经元的输出以超参数p的概率被置为0并对未被置0的神经元的输出进行缩放,缩放比例为1 / (1 - p),因此在训练阶段可以认为是对完整的神经网络的一些子集进行训练,更新这部分子集的参数,注意:训练阶段需要使用model.train()将模型设置为训练模式。
在推理阶段(测试阶段),我们需要停用dropout使用全量神经元进行推理预测,注意:推理阶段需要使用model.eval()将模型设置为评估模式。

在PyTorch中可以使用torch.nn.Dropout(p)来定义一个Dropout层,p即为神经元的失活概率,注意:Dropout层应该添加在激活函数层之后。
6.3.2 批量归一化
批量归一化(Batch Normalization,BN)的计算流程如下:

BN先对输出数据标准化,再对数据进行重构(缩放+平移),γ和β都是可学习的参数,它相当于对标准化后的数据做了一个线性变换,γ为系数,β为偏置, eps是一个极小的数,以避免分母为 0。
注意:对于全连接层来说,计算的是每个特征在其他维度上的均值和方差;而对于卷积层来说,计算的是每个通道在其他维度上的均值和方差。
批量归一化在训练阶段和推理阶段也有不同的表现:
在训练阶段,对数据进行标准化的均值和方差是基于当前批次的样本计算得到的,注意:训练阶段需要使用model.train()将模型设置为训练模式。
在推理阶段(测试阶段)则会使用训练阶段中计算得到的全局均值和全局方差(即训练阶段的各个批次的均值和方差的平均值)对数据进行标准化,注意:推理阶段需要使用model.eval()将模型设置为评估模式。
BN的优点如下:
1. 加速训练:BN能够减少输入数据内部的协变量偏移,加速网络训练,尤其是当网络较深时。
2. 缓解过拟合:BN能够为所有数据添加一定的异常数据的影响,即引入了噪声,因此也属于一种正则化策略,能够提高模型的泛化能力,缓解过拟合。
3. 缓解梯度问题:BN能够规范激活值的分布,避免激活值过大或过小,有效缓解了梯度消失和梯度爆炸的问题。
BN的缺点如下:
1. 计算开销:每次计算均值和方差时需要额外的计算和存储资源,尤其是对于非常深的网络,批量归一化可能带来一定的额外计算开销。
2. 依赖于批量大小:批量归一化的效果受批量大小的影响较大,如果批量太小,mini GD算法会退化为SGD算法,容易受到异常数据的影响,使得均值和方差的估计可能不准确,导致训练不稳定;如果批量太大,mini GD算法会退化为FGD算法,在训练步相同的情况下训练速度较慢,并且有可能陷入局部最优解。
3. 在某些网络架构中不适用:在一些架构中,如循环神经网络(RNN)中,批量归一化的应用可能不如在卷积神经网络(CNN)中那么有效。
在PyTorch中可以使用torch.nn.BatchNorm2d(channels_num)(适用于二维图像数据)或者torch.nn.BatchNorm1d(features_num)(适用于一维线性数据)来定义一个BN层,,BN层应该添加在线性层/卷积层之后,激活函数层之前。
更多推荐


所有评论(0)