局部极小值与鞍点
损失在局部极大值(local maximum)、局部极小值(local minimum)和鞍点(saddle point)的梯度是零。我们把梯度为零的点统称为临界点(critical point)。
对于深度学习中的损失函数而言,我们通常关注的是找到局部或全局极小值,而不是极大值,因为我们的目的是最小化损失。在实践中,由于非凸性以及高维空间的存在,深度学习模型的损失函数可能会有很多局部极小值和鞍点(鞍点处梯度也为零,但不是极值点)。优化算法可能陷入这些点之一,导致训练过程停滞不前。为了避免这种情况,通常会采用一些策略,如动量项、学习率衰减或更高级的优化算法(如Adam、RMSprop等),来帮助模型逃离局部极小值并继续寻找更低的损失值。
判断临界值种类的方法
判断一个临界点到底是局部极小值还是鞍点需要知道损失函数的形状。而网络本身很复杂,用复杂网络算出来的损失函数显然也很复杂。虽然
L
(
θ
)
L(θ)
L(θ) 完整的样子写不出来,但通过泰勒级数近似(Tayler series appoximation) 可得
L
(
θ
)
≈
L
(
θ
′
)
+
(
θ
−
θ
′
)
T
g
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
L(\theta )\approx L({\theta }' ) + (\theta - {\theta }')^{T} g + \frac{1}{2}(\theta - {\theta }')^{T}H(\theta - {\theta }')
L(θ)≈L(θ′)+(θ−θ′)Tg+21(θ−θ′)TH(θ−θ′)
g
g
g 代表梯度,
H
H
H 代表海森矩阵(Hessian matrix)。在临界点,梯度
g
g
g 为零,所以在临界点的附近,损失函数可被近似为
L
(
θ
)
≈
L
(
θ
′
)
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
L(\theta )\approx L({\theta }' ) + \frac{1}{2}(\theta - {\theta }')^{T}H(\theta - {\theta }')
L(θ)≈L(θ′)+21(θ−θ′)TH(θ−θ′)
由此可根据
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
(\theta - {\theta }')^{T}H(\theta - {\theta }')
(θ−θ′)TH(θ−θ′) 判断在
θ
′
{\theta }'
θ′ 附近的误差表面(error surface),进一步可以判断
L
(
θ
′
)
L({\theta }' )
L(θ′) 是局部极小值、局部极大值,还是鞍点。用向量
v
v
v 来表示
(
θ
−
θ
′
)
(\theta - {\theta }')
(θ−θ′) ,有以下三种情况:
- v T H v > 0 v^{T}Hv > 0 vTHv>0. 意味着对于任意 θ {\theta } θ , L ( θ ) > L ( θ ′ ) L(\theta ) > L({\theta }' ) L(θ)>L(θ′). 代表 L ( θ ′ ) L({\theta }' ) L(θ′) 是附近的最低点,所以是局部极小值。
- v T H v < 0 v^{T}Hv < 0 vTHv<0. 意味着对于任意 θ {\theta } θ , L ( θ ) < L ( θ ′ ) L(\theta ) < L({\theta }' ) L(θ)<L(θ′). 代表 L ( θ ′ ) L({\theta }' ) L(θ′) 是附近的最高点,所以是局部极大值。
- v T H v v^{T}Hv vTHv 有时大于零,有时小于零。 意味着在 θ ′ {\theta }' θ′ 附近 , L ( θ ′ ) L({\theta }' ) L(θ′) 既不是局部极大值,也不是局部极小值,而是鞍点。
存在一个问题,通过上述方法判断临界点是局部极小值、鞍点或者局部极大值,需要代入所有的 θ θ θ. 但我们不可能把所有的 v v v 都拿来试试看,所以有一个更简便的方法。算出一个海森矩阵后看其特征值,若 H H H 的所有特征值都为正, H H H 为正定矩阵,则 v T H v > 0 v^{T}Hv > 0 vTHv>0 ;若 H H H 的所有特征值都为负, H H H 为负定矩阵,则 v T H v < 0 v^{T}Hv < 0 vTHv<0 ;若有正有负,则为鞍点。
但实际上,我们几乎不会真的把海森矩阵算出来,因为海森矩阵需要算二次微分,计算这个矩阵的运算量非常大,还要把它的特征值跟特征向量找出来,所以几乎没有人用这个方法来逃离鞍点。还有一些其他逃离鞍点的方法的运算量都比要算海森矩阵小很多。
动量法
作者引用了科幻小说《三体III:死神永生》中的一个情节,来描述如图所示的一维空间中的误差表面,有一个局部极小值。但是在二维空间,这个点就可能只是一个鞍点。(从高维的角度考虑低维的问题)
动量法(momentum method),通过保持对先前梯度方向的记忆来加速朝向最小值的移动,并有助于越过鞍点。
一般的梯度下降(vanilla gradient descent)如左图所示。初始参数为θ0,计算一下梯度,计算完梯度后,往梯度的反方向去更新参数
θ
1
=
θ
0
−
η
g
0
θ_{1} = θ_{0} − ηg_{0}
θ1=θ0−ηg0 。有了新的参数
θ
1
θ_{1}
θ1 后,再计算一次梯度,再往梯度的反方向,再更新一次参数,到了新的位置以后再计算一次梯度,再往梯度的反方向去更新参数。
引入动量后,每次在移动参数的时候,不是只往梯度的反方向来移动参数,而是根据梯度的反方向加上前一步移动的方向决定移动方向。 右图中红色虚线方向是梯度的反方向,蓝色虚线方向是前一次更新的方向,蓝色实线的方向是下一步要移动的方向。把前一步指示的方向跟梯度指示的方向相加就是下一步的移动方向。如右图所示,初始的参数值为 θ 0 = 0 θ_{0} = 0 θ0=0,前一步的参数的更新量为 m 0 = 0 m_{0} = 0 m0=0。接下来在 θ 0 θ_0 θ0 的地方,计算梯度的方向 g 0 g_0 g0。下一步的方向是梯度的方向加上前一步的方向,不过因为前一步正好是0,所以更新的方向跟原来的梯度下降是相同的。但从第二步开始就不太一样了。从第二步开始,计算 g 1 g_{1} g1,接下来更新的方向为 m 2 = λ m 1 − η g 1 m_{2} = λm_{1} − ηg_{1} m2=λm1−ηg1,参数更新为 θ 2 θ_{2} θ2 ,接下来就反复进行同样的过程。每一步的移动都用 m m m 来表示。 m m m 其实可以写成之前所有计算的梯度的加权和,如式所示。其中 η η η 是学习率, λ λ λ 是前一个方向的权重参数,也是需要调的。
m 0 = 0 m 1 = − η g 0 m 2 = − λ η g 0 − η g 1 \begin{align*} & m_{0}=0\\ & m_{1}=-ηg_{0}\\ & m_{2}=-ληg_{0}-ηg_{1} \end{align*} m0=0m1=−ηg0m2=−ληg0−ηg1
引入动量后,可以从两个角度来理解动量法。一个角度是动量是梯度的负反方向加上前一次移动的方向。另外一个角度是当加上动量的时候,更新的方向不是只考虑现在的梯度,而是考虑过去所有梯度的总和。
批量法
实际上在计算梯度的时候,并不是对所有数据的损失L 计算梯度,而是把所有的数据分成一个一个的批量(batch),如图所示。每个批量的大小是 B B B ,即带有 B B B 笔数据。每次在更新参数的时候,会去取出 B B B 笔数据用来计算出损失和梯度更新参数。遍历所有批量的过程称为一个回合(epoch)。事实上,在把数据分为批量的时候,我们还会进行随机打乱(shuffle)。随机打乱有很多不同的做法,一个常见的做法是在每一个回合开始之前重新划分批量,也就是说,每个回合的批量的数据都不一样。
两个极端情况的假设:
- 批量大小为训练数据的大小,这种使用全批量(full batch)的数据来更新参数的方法即批量梯度下降法(Batch Gradient Descent,BGD),此时模型必须把所有练数据都看完,才能够计算损失和梯度,参数才能够更新一次。
- 批量大小等于1,此时使用的方法即随机梯度下降法(Stochastic Gradient Descent,SGD),也称为增量梯度下降法。批量大小等于1 意味着只要取出一笔数据即可计算损失、更新一次参数。如果总共有20 笔数据,那么在每一个回合里面,参数会更新20 次。用一笔数据算出来的损失相对带有更多噪声,因此其更新的方向如图所示,是曲曲折折的 。
考虑到GPU可以进行并行运算,批量大小与计算时间的关系如图所示。假设训练数据只有60000 笔,批量大小设1,要60000 个更新才能“跑”完一个回合;如果批量大小等于1000,60 个更新才能“跑”完一个回合,计算梯度的时间差不多。但60000 次更新跟60 次更新比起来,其时间的差距量就非常大了。因此实际上,在有考虑并行计算的时候,大的批量大小反而是较有效率的,一个回合大的批量花的时间反而是比较少的。
**大的批量更新比较稳定,小的批量的梯度的方向是比较有噪声的(noisy)。**但实际上有噪声的的梯度反而可以帮助训练。
此外,小的批量在测试的时候会是比较好。在论文 “On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima” 中,作者在不同数据集上训练了六个网络(包括全连接网络、不同的卷积神经网络),在很多不同的情况都观察到一样的结果。在小的批量,一个批量里面有256 笔样本。在大的批量中,批量大小等于数据集样本数乘0.1。比如数据集有60000 笔数据,则一个批量里面有6000 笔数据。大的批量跟小的批量的训练准确率(accuracy)差不多,但就算是在训练的时候结果差不多,测试的时候,大的批量比小的批量差,代表过拟合。
下图总结了小批量梯度下降与批量梯度下降的比较。
较大的批量大小可以提高训练效率,但可能影响模型的泛化能力;较小的批量大小有助于提高模型泛化能力,但可能降低训练效率。建议根据具体情况选择合适的批量大小,并考虑使用动量法或其他优化技巧来提高模型的训练效率和泛化性能。
学习小结
通过本次学习,我深入了解了深度学习优化过程中的几个核心概念和技巧,包括局部极小值与鞍点的性质、动量法的工作原理以及批量法在不同批量大小下的表现差异。以下是我的主要收获:
局部极小值与鞍点:
- 损失函数在局部极大值、局部极小值和鞍点处的梯度为零,这些点统称为临界点。
- 通过分析海森矩阵的特征值可以判断临界点是局部极小值、局部极大值还是鞍点。
- 实际上,由于计算海森矩阵及其特征值的计算量较大,实践中通常采用其他方法来帮助模型逃离鞍点。
动量法:
- 动量法通过保留先前梯度方向的记忆来加速朝向最小值的移动,并有助于越过鞍点。
- 动量法的更新规则不仅考虑当前梯度的方向,还考虑之前梯度方向的影响。
- 动量法有助于减少梯度下降过程中遇到的振荡现象,特别是在损失函数曲面具有长而窄的山谷特征时。
批量法:
- 批量梯度下降(BGD)使用全部训练数据来计算梯度,而随机梯度下降(SGD)每次仅使用一个样本更新参数。
- 较大的批量大小可以提高计算效率,但可能导致训练过程较为平稳,缺少逃离局部最小值所需的随机性。
- 较小的批量大小有助于引入噪声,有助于模型逃离鞍点和平坦区域,但可能增加训练时间。
批量大小的影响:
- 较大的批量大小可以利用并行计算的优势,提高训练效率,但可能影响模型的泛化能力。
- 较小的批量大小有助于提高模型的泛化能力,避免过拟合现象,但可能降低训练效率。
实践建议:
- 根据具体情况选择合适的批量大小,并考虑使用动量法或其他优化技巧来提高模型的训练效率和泛化性能。
- 在实践中,可以尝试不同的批量大小,评估它们对模型性能的影响。
通过这次学习,我对如何优化深度学习模型有了更深入的理解,并认识到在实际应用中需要综合考虑多种因素来选择最合适的优化策略。
所有图片来源于Datawhale X 李宏毅苹果书 AI夏令营