深度学习——模型优化
1、优化过程引入
1.1 学习过程和优化过程的区别
- 实际目标不同,学习算法的目标是通过降低损失函数L,从而提高模型在真实情况下的性能P。而优化算法的目标是如何更好的降低损失函数的值。
- 计算目标不同,一般情况下,通过学习算法,我们的计算的是整个模型函数的最小值点。也就是说学习算法通常不会停止在局部值点,而是直接寻找最值点。但是这样容易引起过拟合。但是通过优化算法,其寻找的不一定是最值点,一定程度上,优化函数防止了过拟合。
2、基本优化算法
2. 1随机梯度下降算法SGD
2.1.1 算法描述
- 定义学习率 α α α
- 初始化参数 θ。
- 当没有满足停止条件的时候进行迭代
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 计算梯度估计grad(θ)= 1 m ∑ i L ( f ( X i ; θ ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ),Y_i) m1∑iL(f(Xi;θ),Yi)
- 更新参数 θ n e w = θ − g r a d ( θ ) θ_{new}=θ-grad(θ) θnew=θ−grad(θ)
- 重复4,5,6知道满足停止条件。
一般情况下,对于SGD的学习率还有一个基于某种策略进行变换的过程,随着时间的推移学习率逐渐降低。原因在于SGD中是对m个样本进行计算,而不是针对所有的样本。相当于引入了一定的噪声。
2.2 带有动量的SGD算法
引入动量的目的有两个方面,一个方面是为了解决“峡谷”和“鞍点” 的问题,两个一个方面也是为了加速SGD的收敛。动量算法积累了之前梯度指数级衰减的移动平均,并且继续沿着该方向进行运动。如下图所示:
上图描述的是一个二次的损失函数,红色表示的是带有动量的梯度运动的路径,黑色是没有带有梯度的动量的运动路径,我们可以看出,对于没有带有动量的梯度运动,其在两条等高线之间的运动的幅度要比带有动量的梯度在两条等高线之间运动的幅度要大很多,我们可以理解为两条等高线就是两个山峰,等高线之间是“峡谷”,,通过带有动量的SGD可以很好的减少在“峡谷”中的运动幅度,也就是可以正确的穿过峡谷,同时也加快了冲向最低的速度。
2.2.1 计算过程
- 设置学习率为α,动量参数β
- 初始化参数θ,初始化速度v
- 迭代
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 计算梯度估计 grad(θ)= 1 m ∑ i L ( f ( X i ; θ ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ),Y_i) m1∑iL(f(Xi;θ),Yi)
- 计算速度更新 v n e w = β v − α ∗ g r a d ( θ ) v_{new}=βv-α*grad(θ) vnew=βv−α∗grad(θ)
- 计算参数更新 θ n e w = θ + v θ_{new}=θ+v θnew=θ+v
- 迭代上述过程,直到满足停止条件。
根据基本过程可以看出,之前的SGD更新的步长是学习率与梯度的乘积,现在不仅考虑学习率和梯度的乘积,还考虑了历史的梯度序列的大小和排列,当很多连续的梯度指向的是相同的方向的时候,步长会被不断的增大。
如果动量算法总是观测到某一个梯度g,那么它会在-g的反向是不断的加速,一直到最终速度。在实际使用中,动量参数被β的取值一般为0.5,0.9,1.0,分别对应的是最大2倍,10倍,100倍的步长。
在SGD中,我们说过,学习率可以通过某种参数调整策略进行自适应的调整,同理,动量参数β也可以进行自适应的调整。
2.3 基于Nesterov动量优化
相比于之前的动量计算方法,Nesterov动量采用了一种临时更新的策略,梯度的计算在施加当前速度之后,也就是,我们先用速度是更新参数,然后再去计算梯度,再去更新速度和梯度。具体的算法描述如下:
- 定义学习率α,动量参数β。
- 初始化参数θ,初始化速度v。
- 迭代过程
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 临时更新 θ t = θ + β v θ_{t}=θ+βv θt=θ+βv
- 计算梯度估计 grad(θ)= 1 m ∑ i L ( f ( X i ; θ ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ),Y_i) m1∑iL(f(Xi;θ),Yi)
- 计算速度更新 v n e w = β v − α ∗ g r a d ( θ ) v_{new}=βv-α*grad(θ) vnew=βv−α∗grad(θ)
- 计算参数更新 θ n e w = θ + v θ_{new}=θ+v θnew=θ+v
- 迭代上述过程,直到满足停止条件。
根据上述的算法描述,我们可以发现,相比于之前的动量算法,Nesterov算法增加了一个临时更新的步骤,我们应该如何理解呢?我们可以理解为通过一个提前的变化过程,使得参数增加一个预判能力,所有Nesterov动量可以理解为向标准动量里面添加一个修正因子。
3 自适应学习率算法
在之前的部分,我们描述了几个动量更新算法,我们着重关注了参数的更新过程。接下来,我们来换个角度来思考这个问题,在上面的算法中,无论是SGD还是带有动量的SGD算法,都有一个共同的参数——学习率α,在这之前,学习率一直是我们自己设定的一个超参数,关于设定的方式,并没有什么具体的标准。实际上,学习率对于模型的性能影响是巨大的。一般情况下损失函数高度敏感与参数空间的某些方向,也就是说,在固定学习率的条件下,某些梯度方向下降的特别快,某些参数方向下降的特别慢。为了平衡这种情况,提出一类自适应学习率的算法。也就是学习率会随着参数的变动而变动。
3.1 AdaGrad算法
3.1.1 算法描述
- 设定全局的学习率α。
- 初始化参数θ。
- 定义一个小的常数δ,其值大约在 1 0 − 7 10^{-7} 10−7左右,初始化梯度累积变量r=0.
- 迭代
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 计算梯度估计grad(θ)= 1 m ∑ i L ( f ( X i ; θ ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ),Y_i) m1∑iL(f(Xi;θ),Yi)
- 累积平方梯度 r n e w = r + g r a d ( θ ) ∗ g r a d ( θ ) r_{new}=r+grad(θ)*grad(θ) rnew=r+grad(θ)∗grad(θ)
- 计算梯度更新值 △ θ = − α δ + r ∗ g r a d ( θ ) △θ=-\frac{α}{δ+\sqrt{r}}*grad(θ) △θ=−δ+rα∗grad(θ)
- 更新参数 θ n e w = θ + △ θ θ_{new}=θ+△θ θnew=θ+△θ
- 重复5,6,7,8,9知道满足停止条件。
3.1.2 基本思想
根据上面的算法描述,我们可以看出来一下几个情况:
- 根据梯度更新中的计算,我们可以看出来,对于梯度值较大的参数,其具有一个较大的学习率,梯度较小的参数有一个较小的学习率。具体的来说,每一个参数的学习率的缩放比反比与取历史梯度的平方和的平方根。
- 需要注意到的是,实际上,我们并没有对初始的学习率进行变化,只是在使用的时候进行相应的缩放。
- 基本问题在于:随着梯度的不断累积,学习率被缩放的越来越小,导致最后的学习率变成了一个特别小的值,使得训练变得困难,以至于提前结束。
3.2 RMSProp算法
3.2.1 算法描述
- 初始化学习率α和衰减速率β。
- 初始化参数θ。
- 定义一个小的常数δ,其值大约在 1 0 − 7 10^{-7} 10−7左右,初始化梯度累积变量r=0。
- 迭代
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 计算梯度估计grad(θ)= 1 m ∑ i L ( f ( X i ; θ ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ),Y_i) m1∑iL(f(Xi;θ),Yi)
- 累积平方梯度 r n e w = β r + ( 1 − β ) g r a d ( θ ) ∗ g r a d ( θ ) r_{new}=βr+(1-β)grad(θ)*grad(θ) rnew=βr+(1−β)grad(θ)∗grad(θ)
- 计算梯度更新值 △ θ = − α δ + r ∗ g r a d ( θ ) △θ=-\frac{α}{δ+\sqrt{r}}*grad(θ) △θ=−δ+rα∗grad(θ)
- 更新参数 θ n e w = θ + △ θ θ_{new}=θ+△θ θnew=θ+△θ
- 重复5,6,7,8,9知道满足停止条件。
3.2.2 基本思想
通过上面的算法描述,我们可以发现RMSProp算法的基本思想和Adagrad算法的基本思想几乎一致,但是为了防止由于梯度累积导致的学习率缩放过大,所以设置了衰减速率β来缩放梯度的累积和。
3.2.3 基于Nesterov动量的RMSprop算法
- 初始化学习率α,衰减速率β,动量参数γ
- 初始化参数θ和速度参数v。
- 初始化梯度累积变量r=0。
- 迭代
- 从训练集中采集包含m个样本的小批量 { X 1 , X 2 , . . . , X m } \{X_1,X_2,...,X_m\} {X1,X2,...,Xm},其中每一个样本 X i X_i Xi对应的标签值为 Y i Y_i Yi。
- 计算临时更新 θ t = θ + α v θ_t=θ+αv θt=θ+αv
- 计算梯度估计grad(θ)= 1 m ∑ i L ( f ( X i ; θ t ) , Y i ) \frac{1}{m}∑_iL(f(X_i;θ_t),Y_i) m1∑iL(f(Xi;θt),Yi)
- 累积平方梯度 r n e w = γ r + ( 1 − γ ) g r a d ( θ t ) ∗ g r a d ( θ t ) r_{new}=γr+(1-γ)grad(θ_t)*grad(θ_t) rnew=γr+(1−γ)grad(θt)∗grad(θt)
- 计算速度更新 v n e w = γ v − α r ∗ g r a d ( θ ) v_{new}=γv-\frac{α}{\sqrt{r}}*grad(θ) vnew=γv−rα∗grad(θ)
- 更新参数 θ n e w = θ + v θ_{new}=θ+v θnew=θ+v
- 重复5,6,7,8,9,10直到满足停止条件。
3.3 Adam算法
3.3.1 Adam算法的基本描述
相比于RMSProp算法,Adam算法不仅仅加入了历史梯度平方的衰减,还保留了历史梯度指数衰减平均,可以看做是动量。
4、参数的初始化策略
4.1 标准初始化
一种对于初始化m个输入和n个输出的全连接层的神经网络的权重的启发式方法是从分布
U
(
−
1
m
,
1
m
)
U(-\frac{1}{\sqrt{m}},\frac{1}{\sqrt{m}})
U(−m1,m1)中采用权重。而标准初始化方式则是基于这个启发式的方式:
U
(
−
6
m
+
n
,
6
m
+
n
)
U(-\sqrt{\frac{6}{m+n}},\sqrt{\frac{6}{m+n}})
U(−m+n6,m+n6)
4.2 基于正态分布的初始化
这种初始化的方法以0为中心,标准差为: s t d = 2 i n p u t d i m + o u t p u t d i m std=\sqrt{\frac{2}{input_{dim}+output_{dim}}} std=inputdim+outputdim2的截断的正态分布,其中 i n p u t d i m input_{dim} inputdim为输入的维度, o u t p u t d i m output_{dim} outputdim表示输出的维度。