[深度学习]20170921 优化算法 - xiaobu1986/Notes GitHub Wiki
优化器(optimizers)类的基类。这个类定义了在训练模型的时候添加一个操作的API。你不能直接使用这个类,但是你会用到他的子类比如GradientDescentOptimizer, AdagradOptimizer, MomentumOptimizer等。
Tensorflow文档中提供的子类有
[1] tf.train.GradientDescentOptimizer 梯度下降方法,方法选用参数如下
- learning_rate: A Tensor or a floating point value. The learning rate to use. 学习率
- use_locking: If True use locks for update operations. 如果为True对更新操作使用锁
- name: Optional name prefix for the operations created when applying gradients. Defaults to "GradientDescent".可选名字
[2] tf.train.AdagradOptimizer
上面提到的方法对于所有参数都使用了同一个更新速率。但是同一个更新速率不一定适合所有参数。比如有的参数可能已经到了仅需要微调的阶段,但又有些参数由于对应样本少等原因,还需要较大幅度的调动。Adagrad就是针对这一问题提出的,自适应地为各个参数分配不同学习率的算法。 Δx_t=−η/sqrt(\sum_{τ=1}^{t}g^2_τ+ϵ) 其中g_t同样是当前的梯度,连加和开根号都是元素级别的运算。ϵ是初始学习率,由于之后会自动调整学习率,所以初始值就不像之前的算法那样重要了。而ϵ是一个比较小的数,用来保证分母非0。其含义是,对于每个参数,随着其更新的总距离增多,其学习速率也随之变慢。
Adagrad算法存在三个问题: 1)其学习率是单调递减的,训练后期学习率非常小; 2)其需要手工设置一个全局的初始学习率; 3)更新x_t时,左右两边的单位不同一
[3] tf.train.AdadeltaOptimizer
Adadelta针对Adagrad的上述三个问题提出了解决方案。
-> 首先,针对第一个问题,我们可以只使用adagrad的分母中的累计项离当前时间点比较近的项,如下式: E[g]t^2 = ρ E[g](t-1)^2 + (1-ρ)g_t^2 Δx_t=−η/sqrt(E[g]_t^2+ϵ) * g_t 这里ρ是衰减系数,通过这个衰减系数,我们令每一个时刻的gt随之时间按照ρ指数衰减,这样就相当于我们仅使用离当前时刻比较近的gt信息,从而使得还很长时间之后,参数仍然可以得到更新。
-> 对于问题3,其实sgd跟momentum系列的方法也有单位不统一的情况。何为单位不一致,[Δx的单位 ∝ g的单位 ∝ ∂f/∂x ∝ 1/x的单位]。 牛顿法的单位是正确的,如Δx = H^{-1}t * g_t, [Δx的单位 ∝ H^{-1}g ∝ (∂f/∂x)/(∂(∂f/∂x)/∂x) ∝ ∂x的单位],其中f无单位。 其中H_t为Hessian矩阵,由于其计算量巨大,因而实际中不常使用. 因此,在解决学习率单调递减的问题的方案中,分母已经是∂f/∂x的一个近似了。这里我们可以构造Δx的近似,来模拟得到H{−1}的近似,从而得到近似的牛顿迭代法。
Δx=(∂f/∂x)/(∂2f/∂2x)⇒1/(∂2f/∂2x)=Δx/(∂f/∂x)
Δx_t=−sqrt(E[Δx^2]_{t−1})/sqrt(E[g^2]_t) * g_t
-> 可以看到,如此一来adagrad中分子部分需要人工设置的初始学习率也消失了,从而顺带解决了上述的第二个问题。
[4] tf.train.AdagradDAOptimizer
[5] tf.train.MomentumOptimizer SGD方法的一个缺点是,其更新方向完全依赖于当前的batch,因而其更新十分不稳定。解决这一问题的一个简单的做法便是引入momentum。momentum即动量,它模拟的是物体运动时的惯性,即更新的时候在一定程度上保留之前更新的方向,同时利用当前batch的梯度微调最终的更新方向。这样一来,可以在一定程度上增加稳定性,从而学习地更快,并且还有一定摆脱局部最优的能力: 即Δx_t=ρΔx_{t−1}−ηg_t 其中,ρ 即momentum,表示要在多大程度上保留原来的更新方向,这个值在0-1之间,在训练开始时,由于梯度可能会很大,所以初始值一般选为0.5;当梯度不那么大时,改为0.9。η 是学习率,即当前batch的梯度多大程度上影响最终更新方向,跟普通的SGD含义相同。ρ 与 η 之和不一定为1。
[6] tf.train.AdamOptimizer Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
[7] tf.train.FtrlOptimizer 现在做在线学习和CTR常常会用到逻辑回归( Logistic Regression),而传统的批量(batch)算法无法有效地处理超大规模的数据集和在线数据流,google先后三年时间(2010年-2013年)从理论研究到实际工程化实现的FTRL(Follow-the-regularized-Leader)算法,在处理诸如逻辑回归之类的带非光滑正则化项(例如一阶正则1范数,做模型复杂度控制和稀疏化)的凸优化问题上性能非常出色,据闻国内各大互联网公司都第一时间应用到了实际产品中,我们的系统也使用了该算法。可参考(http://www.cnblogs.com/EE-NovRain/p/3810737.html)
[8] tf.train.ProximalGradientDescentOptimizer 近端梯度下降方法,使得梯度下降方法可以用来求解引入一阶正则项后的损失函数,引入一阶正则后,f(x) = |x|[不可导在0],假设原损失函数为g(x)[凸可导]。
[9] tf.train.ProximalAdagradOptimizer 近端Adagrad方法,使得Adagrad方法可以用来求解引入一阶正则项后的损失函数,引入一阶正则后,f(x) = |x|[不可导在0],假设原损失函数为g(x)[凸可导]。
[10] tf.train.RMSPropOptimizer RMSProp通过引入一个衰减系数,让r每回合都衰减一定比例,类似于Momentum中的做法。即历史数据一定影响优化方向的学习,同时影响步长的学习。
具体实现: 需要:全局学习速率 ϵ, 初始参数 θ, 数值稳定量δ,衰减速率ρ 中间变量: 梯度累计量r(初始化为0) 每步迭代过程:
- 从训练集中的随机抽取一批容量为m的样本{x1,…,xm},以及相关的输出yi
- 计算梯度和误差,更新r,再根据r和梯度计算参数更新量
优点: 相比于AdaGrad,这种方法很好的解决了深度学习中过早结束的问题 适合处理非平稳目标,对于RNN效果很好
缺点: 又引入了新的超参,衰减系数ρ 依然依赖于全局学习速率