深入浅出 Pytorch 系列 — 优化器的选择(1) SGD 和 SGDM

427 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

基本概念

梯度下降

梯度下降(Gradient descent)是一个一阶最优化算法,通常也称为梯度下降法,要使用梯度下降法找到一个函数的局部极小值,向函数上当前点对应梯度(或者是近似梯度)的反方向的规定步长距离点进行迭代搜索。

梯度

梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。

临界点(Critical point)

在数学上,一个可微的实函数或复函数f的临界点是指在f的定义域中导数为 0 的点 。对于一个多变数实函数而言,临界点是在定义域中所有偏导数为 0 的点。

  • 局部最小值(local minima)
  • 鞍点(saddle point)

常用的优化器

  • SGD
  • RMSProp
  • AdaGrad
  • Adam

数学描述梯度下降

θ=argminθ(L(θ))\theta^{*} = \arg min_{\theta}(L(\theta))\\
  • L: Loss
  • θ\theta: Parameters
def gradient_descent(gradient, start, learn_rate, n_iter):
  vector = start
  for _ in range(n_iter):
    diff = -learn_rate * gradient(vector)
    vector += diff
  return vector
  • gradient 是一个函数,也就是 callable object 类型,接收一个参数返回参数梯度
  • start: 序列类型,可以是 list numpy ndarray 或者 tuple
  • learn_rate 学习率
import numpy as np
def gradient_descent(gradient, start, learn_rate, n_iter=50, tolerance=1e-06):
  vector = start
  for _ in range(n_iter):
    diff = -learn_rate * gradient(vector)
    if np.all(np.abs(diff) <= tolerance):
      break
    vector += diff
  return vector

SGD

随机梯度下降: 也叫随机梯度下降法,也就是每次随机从数据集中抽取一个样本然后输入到神经网络进行训练,

小批量(mini batch)随机梯度下降:在计算损失函数时,我们可以一次计算数据集中的所有样本的损失值,然后求均值来作为 Loss 来计算梯度更新参数,也可以将数据集拆分为多批数据,每一次只计算一个批次数据的损失值,然后再去更新一次参数,通常我们都会通过批量数据来计算梯度更新参数。我们将数据集拆分为 N 批次,每个批次样本数量是固定的。

g0=L1(θ0)θ1=θ0ηg0g^0 = \nabla L^1(\theta^0) \\ \theta^1 = \theta^0 - \eta g^0
g1=L1(θ0)θ2=θ1ηg1g^1 = \nabla L^1(\theta^0) \\ \theta^2 = \theta^1 - \eta g^1

小批量随机梯度下降真的快吗

对于批量样本数比较大来说,因为看到样本比较多,所以计算梯度比较准确,所以走位也比较好。不过大家可能认为因为批量样本数量多,所以计算时间可能会比较长。其实经过试验,样本在小于 1000 基本上因为 GPU 并行计算,几乎感觉不到样本数差异带来计算耗时上的差异。

小批量随机梯度下降的优势在哪里

真实因为小批量的 SGD 具有 Noisy 所以每次迭代损失函数差异性,可以让模型学习到更好泛化能力。

SGD with momentum

那么 SGDM 有哪些具体应用呢

  • YOLO
  • Mask RCNN
  • ResNet 以上都是使用 SGDM 优化器来训练,MEMO 也是用 SGDM 训练出来,在不同分类任务中学习到共同特征。

我们可以将 momentum 在物理意义上有动量,也就是物体保持线性运动状态,也可以理解为一阶距。注意这里动量都是梯度,不仅包括方向还有大小。

011.jpeg

v0=0v1=λv0ηL(θ0)θi1=θi0+v1v^0 = 0\\ v^1 = \lambda v^0 - \eta \nabla_L(\theta^0)\\ \theta_i^1 = \theta_i^0 + v^1\\
  • 震荡方向梯度抵消
  • 梯度小的方向累加