梯度下降的变体
批梯度下降
一次更新需要计算整个数据集。速度慢,不允许在线更新模型。对于凸函数可以保证收敛到全局最小值,非凸收敛到局部最小值。
随机梯度下降
一个样本更新一次参数。速度快,可用于在线学习。频繁的更新导致一个大的方差导致损失函数波动明显。当我们慢慢的降低学习速率,收敛行为和批处理方式一样。每轮迭代需要重新打乱样本集。
最小批梯度下降
mini_batch of n
降低了参数更新的方差,使得更稳定的收敛。高效地利用目前深度学习库的矩阵最优化,使得计算梯度效率提高。通常n取50-256之间。是训练神经网络时典型的选择。
for i in range(epochs):
np.random.shuffle(data)
for batch in get_batches(data,batch_size=50):
param_grad=evaluate_gradient(loss_function,batch,params)
params=params-lr*params_grad
挑战
mini-batch不能保证很好的收敛性,而且有一些需要解决的问题。
选择合适的学习率
对于不同参数是否使用相同的学习速率:当数据稀疏和特征不平衡时
避免被困在众多次优局部最小值。困难并非来自局部最小值,而是来自鞍点(一个维度向上倾斜,另一个维度向下倾斜。这些鞍点通常被相同错误值的高原包围,各个方向的梯度为零,使得sgd很难跳出。
梯度下降最优化算法
多种梯度最优化算法被用来处理之前遇到的问题。我么不讨论算法在实际处理高维数据的可用性,比如二阶方法。
=================针对学习率大小是否合适的问题
Momentum
动量法是一种在相关的方向上SGD的加速方法,抑制了震荡。通过引入上一次更新向量的一部分到本次更新向量。
类似:球滚下山坡,积累动量,越来越快
梯度指向相同方向上的动量项增加,并减少了梯度改变方向上的更新。结果,获得了更快的收敛速度并减小了震荡。
- momentum表示要在多大程度上保留原来的更新方向。在训练开始时,由于梯度可能会很大,所以初始值一般选择0.5,当梯度不那么大时,为了减小震荡,增大动量的作用,改为0.9。
Nesterov
类似:我们需要更智能的球,不单单盲目的沿着坡度向下滚动,而且可以知道自己所处的位置,并且在坡度上升之前停下来。
对传统动量的一种改进:先按照原来的更新方向更新一步,然后求该处的梯度值,用这个梯度值修正最终的更新方向。
这种预期的更新可以防止我们的速度太快,显著提高了RNN在很多任务上的性能。
================现在我们能够将更新调整到错误函数的斜率,并反过来加速SGD 的更新,我们还希望根据每个参数的重要程度来调整对单个参数的更新。
AdaGrad
有的参数已经到了仅需要微调的阶段,有的参数由于对应的样本少等原因,还需要较大幅度的调动。
该算法可以自适应的为各个参数分配不同的学习率。极大的提高了SGD的强壮性,并且谷歌用它来训练大规模的神经网络。
每个参数不同次的更新的学习速率都是可变的。基于对该参数之前的梯度平方求和来影响学习率。
缺点:随着更新次数的增多,由于梯度的平方是正的,所以梯度平方和不断增大,可能使得学习率
η÷√(Gt+ϵ)
急剧减小,到无限,此时更新将没有意义,没有新的更新内容。
需要手动设置
η
Adadelta
是AdaGrad 的延伸,解决了学习率单调递减的问题。
并不是累加所有过去的梯度平方。限制了过去的梯度累加的窗口尺寸w,对过去梯度平方增加了指数衰减。
RMSprop
和Adadelta相同的时间独立的提出,都是为了解决adagrad学习率急速递减的问题。是Adadelta的一个特例。 γ 设为0.9, η 设为0.001
Adam:自适应矩估计
是另一种为每个参数计算自适应学习率的算法。对于过去的梯度平方增加了一个指数衰减,对过去的梯度也增加了一个指数衰减。
AdaMax
Nadam
算法可视化
选择哪一个最优化方法?
- 如果你的数据是稀疏的,用自适应学习速率的方法。
- RMSprop 、Adadelta、Adam相似。不过Adam由于增加了基值矫正使得在后期梯度变得稀疏时表现的更好。所以Adam是最好的选则。
- SGD通常可以收敛到一个最小值,不过可能比运用优化器需要的时间更长,并且依赖于你的初始化和退火策略,而且容易被困在鞍点。如果你关心收敛速度和训练深的网络,应该选择自适应学习速率的方法。