优化器

学习 · 2022-10-18 · 858 人浏览

优化器

前言

优化器是引导神经网络更新参数的工具,深度学习在计算出损失函数之后,需要利用优化器来进行反向传播,完成网络参数的更新。

在这个过程中,便会使用到优化器,优化器可以利用计算机数值计算的方法来获取损失函数最小的网络参数。在深度学习中,不同的优化器只是定义了不同的一阶动量和二阶动量,一阶动量是与梯度相关的函数,二阶动量是与梯度平方相关的函数。常用的优化器主要有随机梯度下降法MomentumAdaGradRMSPropAdam优化器。

神经网络利用优化器来更新网络参数步骤如下:

  1. 计算当前时刻t损失函数关于网络参数w的梯度

$$ g_t=\nabla loss= \frac{\partial loss}{\partial(w_t)} $$

  1. 计算当前时刻t一阶动量$m_t$和二阶动量$V_t$
  2. 计算当前时刻t下降梯度

$$ \eta_t=lr\bullet m_t / \sqrt{V_t} $$

  1. 计算下一时刻t+1参数

$$ w_{t+1}=w_t-\eta_t=w_t-lr \bullet m_t / \sqrt{V_t} $$

SGD 随机梯度下降法

目前,神经网络最常用的为随机梯度下降(Stochastic Gradient Descent,SGD),其基本思想是将数据分成n个样本,通过计算各自梯度的平均值来更新梯度,即对网络参数w更新过程中不需要全部遍历整个样本,而是只看一个训练样本(batch size)使用梯度下降进行更新,然后利用下一个样本进行下一次更新。

SGD简单且容易实现,解决了随机小批量样本的问题,由于只对一个训练样本进行梯度下降,可以提高网络参数的更新速度;但其训练时下降速度慢、准确率下降、容易陷入局部最优以及不容易实现并行处理等问题。

$$ \begin{aligned} 一阶动量&: m_t=g_t \\ 二阶动量&: V_t=1\\ 下降梯度&:\eta_t=lr\bullet m_t / \sqrt{V_t}=lr \bullet g_t\\ 参数更新&:w_{t+1}=w_t-lr\bullet \frac{\partial loss}{\partial w_t}=w_t-\eta_t=w_t-lr\bullet m_t/ \sqrt{V_t}=w_t-lr\bullet g_t \end{aligned} $$

函数:

class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)

'''
参数:
    params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    lr (float) – 学习率
    momentum (float, 可选) – 动量因子(默认:0)
    weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
    dampening (float, 可选) – 动量的抑制因子(默认:0)
    nesterov (bool, 可选) – 使用Nesterov动量(默认:False)
'''

Momentum

SGD训练时仍然存在着收敛速度慢,容易陷入局部最优解的问题。

Momentum则是通过引入动量的方式来加快学习过程,主要思想是积累之前梯度指数级衰减的移动平均。

SGD每次都会在当前位置沿梯度负方向更新,不会考虑先前的梯度方向及大小;Momentum则是通过引入一个新的变量v去积累之前的梯度,从而可以加速网络的学习过程,也就是说如果当前时刻的梯度方向与之前时刻累计的梯度方向一致,那么梯度会加强,梯度下降的幅度更大,反之,梯度下降的幅度会降低。

$$ \begin{aligned} 一阶动量&:m_t=\beta\bullet m_{t-1}+(1-\beta)g_t\\ 二阶动量&:V_t=1\\ 下降梯度&:\eta_t=lr\bullet m_t/ \sqrt{V_t}=lr\bullet m_t=lr\bullet (\beta\bullet m_{t-1}+(1-\beta)\bullet g_t)\\ 参数更新&: w_{t+1}=w_t-lr\bullet \frac{\partial loss}{\partial w_t}=w_t-\eta_t=w_t-lr\bullet (\beta\bullet m_{t-1}+(1-\beta)\bullet g_t) \end{aligned} $$

AdaGrad

针对SGD与Momentum存在的问题,AdaGrad(Adaptive Gradient)是在SGD基础上引入二阶动量,能够对不同的参数使用不同的学习率进行更新,对于梯度较大的参数,那么学习率就会变得较小;而对于梯度较小的参数,那么学习率就会变得较大,这样就会使在陡峭的区域下降速度快,平缓的区域下降速度慢。

由公式可以看出,二阶动量Vt表示累计梯度的平方,一段时间后,Vt就会非常大,导致学习率变得非常小,设置会导致梯度消失的问题。

$$ \begin{aligned} 一阶动量&:m_t=g_t\\ 二阶动量&: V_t=\sum^T_{t=1}g_t^2\\ 下降梯度&:\eta_t=lr\bullet m_t/ \sqrt{V_t} = lr\bullet g_t/(\sqrt{\sum_{t=1}^Tg_t^2})\\ 参数更新&:w_{t+1}=w_t-lr\bullet \frac{\partial loss}{\partial w_t}=w_t-lr\bullet g_t /(\sqrt{\sum^T_{t=1}g_t^2}) \end{aligned} $$

RMSProp

RMSProp是对AdaGrad的一个扩展,在非凸情况下效果更好。RMSProp在SGD的基础上增加了二阶动量,二阶动量Vt使用指数滑动平均值计算来调节学习率,代表过去一段时间的平均值。能够在目标函数不稳定的情况下很好的收敛,且能够快速收敛。

RMSProp能够避免梯度快速降低的问题,学习率自适应能力较强,且能够在目标函数不稳定的情况下快速的收敛,比上述三种优化器表现都好。

$$ \begin{aligned} 一阶动量&: m_t=g_t\\ 二阶动量&:V_t=\beta\bullet V_{t-1}+(1-\beta)\bullet g^2_t\\ 下降梯度&: \eta_t=lr\bullet m_t / \sqrt{V_t}=lr\bullet g_t/(\sqrt{\beta\bullet V_{t-1}+(1-\beta)\bullet g_t^2})\\ 参数更新&:w_{t+1}=w_t-lr\bullet \frac{\partial loss}{\partial w_t}=w_t-\eta_t=w_t-lr \bullet g_t/(\sqrt{\beta\bullet V_{t-1}+(1-\beta)\bullet g_t^2}) \end{aligned} $$

Adam

Adam是将Momentum与RMSProp结合起来的一种算法,引入了Momentum的一阶动量来累计梯度与RMSProp的二阶动量可以使得收敛速度快的同时使得波动幅度小,然后在此基础上增加了两个修正项,能够实现参数自新。

Adam优化器具有以下优点:

  1. 实现简单,计算高效,对内存需求少
  2. 参数的更新不受梯度的伸缩变换影响
  3. 超参数具有很好的解释性,且通常无需调整或仅需很少的微调
  4. 更新的步长能够被限制在大致的范围内(初始学习率)
  5. 能自然地实现步长退火过程(自动调整学习率)
  6. 很适合应用于大规模的数据及参数的场景
  7. 适用于不稳定目标函数
  8. 适用于梯度稀疏或梯度存在很大噪声的问题

$$ \begin{aligned} 一阶动量&: m_t=\beta_1\bullet m_{t-1}+(1+\beta_1)\bullet g_t\\ 修正一阶动量的偏差&:\hat{m}_t=\frac{m_t}{1-\beta^t_1}\\ 二阶动量&:V_t=\beta_2\bullet V_{step-1}+(1-\beta_2)\bullet g_t^2\\ 修正二阶动量的偏差&:\hat{V}_t=\frac{V_t}{1-\beta_2^t}\\ 下降梯度&:\eta_t=lr\bullet \hat{m}_t/ \sqrt{\hat{V}_t}=lr\bullet \frac{m_t}{1-\beta^t_1}/(\sqrt{\frac{V_t}{1-\beta^t_2}})\\ 参数更新&:w_{t+1}=w_t-lr\bullet \frac{\partial loss}{\partial w_t}=w_t-\eta_t=w_t-lr\bullet \frac{m_t}{1-\beta^t_1}/(\sqrt{\frac{V_t}{1-\beta^t_2}}) \end{aligned} $$

class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)[source]

'''
参数:
    betas (Tuple[float, float], 可选) – 用于计算梯度以及梯度平方的运行平均值的系数(默认:0.9,0.999)
    eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
'''
优化器
Theme Jasmine by Kent Liao