0%

深度学习优化器

梯度下降思想

Gradient Descent 的核心思想非常的简单。针对一个模型,我们最终希望它的(非负的)损失函数最小:𝜽 = argmin J(𝜽)

根据 Gradient Descent on Wikipedia,GD 秉持一个最朴素的思想:J'(𝜽) 指向哪里,沿着它的反方向 -J'(𝜽) 走(即 𝜽_next = 𝜽_now - J'(𝜽)),就能让 J(𝜽) 降低。

梯度下降公式:

1
2
3
𝜽_next = 𝜽_now - 𝜺*J'(𝜽)

𝜺为学习率。

BGD

每次计算整个训练集损失函数的均值,然后求导进行更新。

由于这种方法是在一次更新中,就对整个数据集计算梯度。

存在两个问题:

  • 计算速度慢
  • 计算占用内存大

所以几乎无法投入实际使用

SGD

每次对单个样本计算损失函数和梯度,然后进行更新。

存在问题:

  • 存在较大的噪声,损失函数存在较大的震荡。

BGD可能收敛到局部最优点,SGD震荡可以跳出局部最优点,到达更好的最优点。

Mini-batch SGD

结合BGD和SGD的特点,每次利用训练集的一部分样本更新模型。

存在问题:

但是每次使用小部分数据更新模型,这小部分数据的梯度与整体数据的梯度可能存在偏差,还是会存在震荡。

Momentum

单批样本更新存在偏差,那么就不要全速更新,一定程度上保留之前的梯度。颇有引入惯性定理的味道。

1
2
3
4
v_t+1 = 𝝁v_t - 𝜺J'(𝜽_t)
𝜽_t+1 = 𝜽_t + v_t+1

𝜺 是学习率,𝝁 则为一个取值 [0,1] 的动量系数。

Nesterov Momentum

Momentum算法的改进版

1
2
v_t+1 = 𝝁v_t - 𝜺J'(𝜽_t + 𝝁v_t)
𝜽_t+1 = 𝜽_t + v_t+1

区别在于,将梯度计算放在施加当前速度之后。相当于计算梯度时,按照全局趋势先走半步,进一步减小偏差。

以上算法在各个维度上的下降速度是一致的。然而在实际情况中,损失函数对不同的维度的敏感度是不一样的,因此对不同维度设置不同的学习率是一种比较好的方式。以下自适应学习率的方法即是这种思想的体现。

Delta-bar-delta

基于一种简单的思想:

  1. 如果过去两次更新的梯度符号相同,代表方向正确,增大更新时的步长
  2. 如果过去两次更新的梯度符号相反,代表方向不定,缩小更新时的步长

这种方法只能用在全批量优化中,在 Mini-Batch 上却不好。每个 Mini-Batch 之间的差别会使得每一次更新本身的步长就会有很大的差异,这一点和全量数据更新时有比较明显的差异。

Adagrad

累计所有参数的历史梯度平方和,参数学习率与梯度平方和2次方根成反比。达到的效果是:

  • 在陡坡,学习率变小

  • 在平地,学习率变大

1
2
3
r = r + g^2

𝜽_t+1 = 𝜽_t - e/(o + r)^0.5 * g

存在问题:

  • 学习率过度减小

适合凸函数优化

  • 优化器需要要对每个参数保存一个中间值,占用内存参数的两倍。

RMSProp

Hinton改进Adagrad算法适用于非凸优化场景。

加入指数衰减,丢弃遥远过去的历史:

1
2
3
r = p*r + (1-p)g^2

𝜽_t+1 = 𝜽_t - e/(o + r)^0.5 * g

这种算法被证明是深度学习模型中非常有效的一种方法。

  • 优化器需要要对每个参数保存一个中间值,占用内存参数的两倍。

Adadelta

1
2
3
4
5
6
r = p*r + (1-p)g^2

对梯度下降的速度也做一个估计,用来当作学习率
e = p*e + (1-p)𝜽^2

𝜽_t+1 = 𝜽_t - e^0.5/(o + r)^0.5 * g

不用设定学习率。

  • 优化器需要要对每个参数保存2个中间值,占用内存参数的三倍。

Adam

集合RMSProp和动量算法

1
2
3
4
5
6
7
8
9
10
11
m_t = 𝜷_1*m_t-1 + (1 - 𝜷_1)*J'(𝜽)

v_t = 𝜷_2*v_t-1 + (1 - 𝜷_2)*J'(𝜽)^2

对期望和方差做修正:
m_hat_t = m_t / (1 - 𝜷_1^t)
v_hat_t = v_t / (1 - 𝜷_2^t)

𝜽_w,t = 𝜽_w,t-1 - 𝜂*m_hat_t/(sqrt(v_hat_t) + 𝜺)

𝜺 是一个用以保证数值稳定的一个很小的值。
  • 优化器需要要对每个参数保存2个中间值,占用内存参数的三倍。

优化器效果对比

如果数据是稀疏的,就用自适用方法,即 Adagrad, Adadelta, RMSprop, Adam。

RMSprop, Adadelta, Adam 在很多情况下的效果是相似的。

Adam 就是在 RMSprop 的基础上加了 bias-correction 和 momentum,

随着梯度变的稀疏,Adam 比 RMSprop 效果会好。

整体来讲,Adam 是最好的选择

很多论文里都会用 SGD,没有 momentum 等。SGD 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点

如果需要更快的收敛,或者是训练更深更复杂的神经网络,需要用一种自适应的算法。