优化问题综述(一)无约束最优化问题的解法中用于神经网络的常见算法

优化问题是解决形如

minxg(x)+h(x),s.t.,xX

的问题,g(x)是损失函数,h(x)是正则化约束,X是可行域。
我们令f(x)=g(x)+h(x),对f(x)已知信息的多少可把这个问题分为

  • 2阶问题:已知f(x)的函数值、1阶、2阶导数(值、梯度、hessen矩阵)
  • 1阶问题:已知f(x)的函数值、1阶导数(值、梯度)
  • 0阶问题:只知道f(x)的函数值(值)
  • -1阶问题:只知道f(x)的估计值F[f(x),ξ]

当可行域X为整个空间时,优化问题被成为无约束的最优化问题;当可行域X受到限制时,优化问题被成为有约束的最优化问题。

无约束最优化问题的解法

我们希望得到minxf(x),我们把f(x)泰勒展开可得

f(x+Δ)=f(x)+f(x)TΔ+ΔT2f(x)Δ+O(Δ3)

1阶问题中用于神经网络的常见算法

f(x)已知时,我们可知,将x往与f(x)相反的方向走一小步Δf(x+Δ)会下降,那么我们可以得到递推公式

xt+1=xtηf(xt)

η为步长大小。观察递推公式,我们可知可以从步长η和梯度f(xt)进行优化。

Gradient Descent Optimizer

tf.train.GradientDescentOptimizer(learning_rate, name=’GradientDescent’)

最朴素的算法,直接利用梯度递推公式进行优化,步长可为定值或指数衰减。
他的缺点很明显:

  • 很难选择出合适的学习率
  • 相同的学习率并不适用于所有的参数
  • 在神经网络中,非凸问题关键是要避免陷入局部最小值或自鞍点,梯度下降法并不能很好的解决

Momentum Optimizer

tf.train.MomentumOptimizer(learning_rate, momentum, use_nesterov=False, name=’Momentum’)

添加上步的更新分量到当前,可以一定程度上避免陷入局部最小值或自鞍点。直观的理解就是给运动加上了惯性。与梯度下降相比,加速收敛,提高精度(减少收敛过程中的振荡)。递推公式为

V(t)=γV(t1)+(1γ)f(xt)

xt+1=xtηV(t)

γ一般设置为0.9。

Nesterov Momentum Optimizer

tf.train.MomentumOptimizer(learning_rate, momentum, use_nesterov=True, name=’Momentum’)

添加上步的更新分量到当前,并预测下一时刻的动量来修正。递推公式为

V(t)=γV(t1)+(1γ)f(xtηV(t1))

xt+1=xtηV(t)

Adagrad

tf.train.AdagradOptimizer(learning_rate, initial_accumulator_value=0.1, name=’Adagrad’)

对稀疏参数(例如神经网络中有些**函数**的概率很低,那相应通路上的参数就很难进行更新)进行大幅更新和对频率参数小幅更新,适合处理稀疏数据。递推公式:

xt+1,i=xt,iηGt,i+ϵgt,i,Gt,i=τ=1tgτ,i2

gt,i是梯度的第i个分量。梯度较大的减小步长,防止跑过,梯度较小增加步长,加速。缺点步长总是在衰减。
直观的理解各分量步长不同可以想象优化的loss函数等高线并不是一个球,而是一个椭球,当然最快的下降线路并不是沿等高线的法线(梯度方向),而是有个偏斜,Adagrad就是解决这个问题的。

Adadelta

tf.train.AdadeltaOptimizer(learning_rate=0.001, rho=0.95, epsilon=1e-08, name=’Adadelta’)

训练初中期,加速效果很好,后期会抖动,不需要设置步长。递推公式为:

Gt,i=γGt1,i+(1γ)gτ,i2

xt+1,i=xt,iτ=1tΔxτ,i2Gt,i+ϵgt,i

Adadelta的直观理解是使得更新的Δx的量纲与x相同,而且gτ,i2Gt,i的影响指数衰减,所以采用这种形式。

RMSprop

tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.0, epsilon=1e-10, name=’RMSProp’)

与Adadelta对于Gt,i处理想法相同, gτ,i2Gt,i的影响指数衰减。

Gt,i=12Gt1,i+12gτ,i2

xt+1,i=xt,iηGt,i+ϵgt,i

Adam

tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, name=’Adam’)

相当于给梯度加入了动量。

梯度的一阶矩估计:mt=μmt1+(1μ)gt
梯度的二阶矩估计:nt=μnt1+(1γ)gt2
校正:m^t=mt1μt,n^t=nt1γt
校正的原因是因为初始时mt=nt=0mt会偏小,放大修正。
递推公式:xt+1=xtαm^tn^t+ϵ

Adam的变体

Adamax:nt=max(γnt1,|gt|),xt+1=xtαm^tnt+ϵ
对梯度的学习率范围有了更好的约束

Nadam:带有Nesterov动量项的Adam
梯度:g^t=gt1μt
梯度的一阶矩估计:mt=μmt1+(1μ)gt,m^t=mt1μt,m¯t=(1μ)g^t+μm^t
梯度的二阶矩估计:nt=μnt1+(1γ)gt2,n^t=nt1γt
递推公式:xt+1=xtαm¯tn^t+ϵ

Adam+GD

由于GD一般训练时间更长,容易陷入鞍点, 但在好的初始化和学习率调度方案下,结果更可靠。
更为复杂的方法收敛速度快,但是在最优点附近没有GD收敛的效果好。
那么我们可以先Nadam到最优点附近,再切换SGD,具体做法是
先用Nadam进行优化,每隔150步学习速率衰减10倍,计算Nadam及等效学习速率,当学习速率几乎不变时,切换GD,GD的学习速率为Nadam此时的等效学习速率。

  • Inputs: Objective function f, initial point θ0, learning rate α=103, accumulator
    (β1,β2)=(0.9,0.999),ϵ=109, phase=Adam
  • Initialize: k=0, m0=0, n0=0, λ0=0
  • while stopping criterion not met do
    • k=k+1
    • Compute stochastic gradient gk=f(θk1)
    • If phase=SGD then
      • vk=β1vk1+gk
      • θk=θk1(1β1)ηvk
      • continue
    • End if
    • mk=β1mk1+(1β1)gk
    • αk=β2αk1+(1β2)gt2
    • pk=αk1β2k1β1kmkαk+ϵ
    • if pkTgk0 then
      • γk=pkTpkpkTgk
      • λk=β2λk1+(1β2)γk
      • if k>1 and |λk1β22λk1|<ϵ then
        • phase = SGD
        • $v_k=0
        • η=λk1β22
      • end if
    • else
      • λk=λk1
    • end if
  • end while
  • return θk

一般形式

梯度的一阶矩估计:mt
梯度的二阶矩估计:nt
递推公式:xt+1=xtαmtnt+ϵ

两招加速:动量(Nesterov),二阶矩

可视化

优化问题综述(一)无约束最优化问题的解法中用于神经网络的常见算法

加了二阶矩的优化算法看起来比只加动量的从收敛速度和最终精度来看,都要好一些。

tf中的其他Optimizer

tf.train.SyncReplicasOptimizer # 多个Optimizer同步
tf.train.FtrlOptimizer # FTRL算法,加L1正则的感觉
tf.train.ProximalGradientDescentOptimizer # 加L1,L2正则
tf.train.ProximalAdagradOptimizer # 加L1,L2正则