7.1优化与深度学习
优化:优化算法的目标函数通常是一个基于训练数据集的损失函数,优化的目标在于降低训练误差。
深度学习:深度学习的目标在于降低泛化误差。为了降低泛化误差,除了使用优化算法降低训练误差以外,还需要注意应对过拟合。
梯度接近0时,是为局部最优点或鞍点:由于学习模型参数维度通常是高维,所以鞍点比局部最小值更常见。
输入是n维向量x=[x1,x2,…,xn]⊤海森矩阵H=∂x12∂2f∂x2∂x1∂2f⋮∂xn∂x1∂2f∂x1∂x2∂2f∂x22∂2f⋮∂xn∂x2∂2f……⋱…∂x1∂xn∂2f∂x2∂xn∂2f⋮∂xn2∂2f, 当函数的海森矩阵在梯度为0的位置上的特征值全为正时,该函数得到局部最小值。
当函数的海森矩阵在梯度为0的位置上的特征值全为负时,该函数得到局部最大值。
当函数的海森矩阵在梯度为0的位置上的特征值有正有负时,该函数得到鞍点。
对于k维参数,第一种的概率是0.5^k。显然鞍点的概率大。
两个挑战:局部最小值和鞍点
低维空间的非凸优化问题:主要是存在一些局部最优点。采用梯度下降方法时,不合适的参数初始化会导致陷入局部最优点,因此主要的难点是如何选择初始化参数和逃离局部最优点。 高维空间中非凸优化的难点:并不在于如何逃离局部最优点,而是如何逃离鞍点。鞍点(saddle point)是梯度为0,但是在一些维度上是最高点,在另一些维度上是最低点。
练习
对于深度学习中的优化问题,你还能想到哪些其他的挑战?
答:学习率的调整,如何选择初始化参数。
7.2梯度下降
numpy.meshgrid()——生成网格点坐标矩阵
举例:X轴可以取三个值1,2,3, Y轴可以取三个值7,8, 请问可以获得多少个点的坐标?
# 坐标向量
a = np.array([1,2,3])
# 坐标向量
b = np.array([7,8])
# 从坐标向量中返回坐标矩阵
# 返回list,有两个元素,第一个元素是X轴的取值,第二个元素是Y轴的取值
res = np.meshgrid(a,b)
#返回结果: [array([ [1,2,3] [1,2,3] ]), array([ [7,7,7] [8,8,8] ])]
# (1,7)(2,7)(3,7)(1,8)(2,8)(3,8)
学习率过大或过小都有问题。一个合适的学习率通常是需要通过多次实验找到的。
当训练数据集的样本较多时,梯度下降每次迭代的计算开销较大O(n),因而随机梯度下降通常更受青睐O(1)。理解:梯度下降需要梯度求和后取平均,随机梯度下降只采样一个来计算梯度。
练习
使用一个不同的目标函数,观察梯度下降和随机梯度下降中自变量的迭代轨迹。
答:梯度下降比较线性,随机梯度下降比较曲折。
在二维梯度下降的实验中尝试使用不同的学习率,观察并分析实验现象
答:小于0.5的还可以用,超过的无法收敛。学习率偏低会导致无法接近0点,稍高会在0点附近徘徊,过高则不收敛。猜测过高导致了接近指数爆炸的效果。
7.3小批量随机梯度下降
小批量随机梯度下降中每次迭代的计算开销为O(|B|)。
当批量大小等于训练数据样本数时,该算法即梯度下降。
练习
修改批量大小和学习率,观察目标函数值的下降速度和每个迭代周期的耗时。
答:批量小,每个迭代周期耗时长,下降速度快。近似随机梯度下降。
学习率提高,梯度下降速度越快,每个迭代周期耗时不影响。
查阅MXNet文档,使用Trainer
类的set_learning_rate
函数,令小批量随机梯度下降的学习率每过一个迭代周期减小到原值的1/10。
答:在迭代周期的循环中添加如下代码。
trainer_hyperparams['learning_rate'] /= 10
trainer.set_learning_rate(trainer_hyperparams['learning_rate'])
print(trainer_hyperparams['learning_rate'])
7.4动量法
换句话说,相比于小批量随机梯度下降,动量法在每个时间步的自变量更新量近似于将前者对应的最近1/(1−γ)个时间步的更新量做了指数加权移动平均后再除以1−γ。所以,在动量法中,自变量在各个方向上的移动幅度不仅取决于当前梯度,还取决于过去的各个梯度在各个方向上是否一致。这样,我们就可以使用较大的学习率,从而使自变量向最优解更快移动
动量γ=0.5,则是1/(1-γ)=2倍小批量梯度下降。
动量γ=0.9,则是1/(1-γ)=10倍小批量梯度下降。
后者是前者五倍,直觉上,后者学习率应该是前者1/5.
练习
使用其他动量超参数和学习率的组合,观察并分析实验结果。
答:momentum越小,结果越不陡。原因:动量越小,相当于越小批量的梯度下降,所以损失降低慢。其他组合改变如上述笔记。
7.5AdaGrad算法
AdaGrad算法,它根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,从而避免统一的学习率难以适应所有维度的问题。
首先,小批量随机梯度gt按元素平方后累加到变量stst←st−1+gt⊙gt,然后,目标函数自变量中每个元素的学习率通过按元素运算重新调整一下xt←xt−1−st+ϵη⊙gt,其中,η是学习率,ϵ是为了维持数值稳定性而添加的常数, 总结
AdaGrad算法在迭代过程中不断调整学习率,并让目标函数自变量中每个元素都分别拥有自己的学习率。
使用AdaGrad算法时,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。(AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。)
练习
在介绍AdaGrad算法的特点时,我们提到了它可能存在的问题。你能想到什么办法来解决这个问题?
答:AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。解决办法:学习率降低的慢一点?指数加权移动平均。
在实验中尝试使用其他的初始学习率,结果有什么变化?
答:损失函数变得曲折了起来。
7.6RMSProp算法
MSProp算法使用了小批量随机梯度按元素平方的指数加权移动平均来调整学习率。改进了AdaGrad算法。
st←γst−1+(1−γ)gt⊙gtxt←xt−1−st+ϵη⊙gt 因为RMSProp算法的状态变量s_t是对平方项g_t⊙g_t的指数加权移动平均,所以可以看作最近1/(1−γ)个时间步的小批量随机梯度平方项的加权平均。
在同样的学习率下,RMSProp算法可以更快逼近最优解。
练习
把γ的值设为1,实验结果有什么变化?为什么?
答:损失函数发散扩大,而后Maximum allowed size exceeded。即获得nan。因为一开始的s_t为0,一直没有增长。后面学习率η除以ε的开根号,所得的值,导致自变量降低很大。
试着使用其他的初始学习率和γ超参数的组合,观察并分析实验结果。
答:原来:初始学习率0.01 和γ超参数0.9
修改1:初始学习率0.01 和γ超参数0.99-------结果:损失函数比原来更快下降。因为s_t变小,所以学习率更容易变大。
修改2:初始学习率0.05 和γ超参数0.90-------结果:损失函数比原来更快下降,后期更曲折,有增有减。因为η变大,所以学习率更容易变大。后期由于学习率还是增大,所以变得曲折。
7.7AdaDelta算法
st←ρst−1+(1−ρ)gt⊙gtgt′←st+ϵΔxt−1+ϵ⊙gtxt←xt−1−gt′Δxt←ρΔxt−1+(1−ρ)gt′⊙gt′. 小批量随机梯度g_t按元素平方的指数加权移动平均变量s_t
超参数0≤ρ<1(对应RMSProp算法中的γ)
状态变量Δx_t,在时间步0时被初始化为0。记录自变量变化量g′t按元素平方的指数加权移动平均。
AdaDelta算法没有学习率超参数,它通过使用有关自变量更新量平方的指数加权移动平均的项
Δxt−1 来替代RMSProp算法中的学习率。
练习
调节AdaDelta算法中超参数ρ的值,观察实验结果。
答:有点类似学习率,增大就容易降低损失。但是直觉上觉得,比学习率更稳定可靠。
7.8Adam算法
时间步t的动量变量vt←β1vt−1+(1−β1)gtst←β2st−1+(1−β2)gt⊙gt修正偏差v^t←1−β1tvt修正偏差s^t←1−β2tstgt′←s^t+ϵηv^t用g′t迭代自变量xt←xt−1−gt′. 0<=β_1<1,作者建议0.9
0<=β_2<1,作者建议0.999
小批量随机梯度gt按元素平方的指数加权移动平均变量st
注:之前AdaDelta算法是只有按元素平方的,而Adam是增加了没有平方的小批量随机梯度也做指数加权移动平均。
总结
Adam算法在RMSProp算法的基础上对小批量随机梯度也做了指数加权移动平均。
练习
调节学习率,观察并分析实验结果。
答:高于0.03就效果不太好了,迭代后期产生了曲折变化。原因想不明白。目前来看,Adam的学习率应当低一点
有人说Adam算法是RMSProp算法与动量法的结合。想一想,这是为什么?
答:因为对小批量随机梯度做指数加权移动平均就是动量法。