小小白祈祷中...

在深度学习和机器学习的模型训练过程中,优化算法起着至关重要的作用。除了标准的梯度下降和动量优化器之外,还有许多自适应学习率的优化算法,如 AdagradAdadeltaRMSProp。它们通过自适应地调整学习率,以提升收敛速度和稳定性。

以下将详细介绍这三个优化算法,包括公式、原理,以及 Python 代码实现。


Adagrad 算法

背景与动机

在标准的梯度下降过程中,学习率 η\eta 是一个全局的超参数,对所有参数 θ\theta 都保持不变。在某些情况下,不同参数的特性可能差异很大,使用相同的学习率可能导致收敛效果不佳。

Adagrad(Adaptive Gradient Algorithm)算法通过为每个参数引入不同的自适应学习率,根据历史梯度信息动态调整参数的更新步长,特别适合处理稀疏数据高维特征

数学公式

Adagrad 的参数更新规则:

对于每个参数 θi\theta_i,有:

  1. 累积历史梯度的平方和:

Gt,i=Gt1,i+[θiJ(θt)]2G_{t,i} = G_{t-1,i} + [\nabla_{\theta_i} J(\theta_t)]^2

  1. 更新参数:

θt+1,i=θt,iηGt,i+ϵθiJ(θt)\theta_{t+1,i} = \theta_{t,i} - \frac{\eta}{\sqrt{G_{t,i} + \epsilon}} \nabla_{\theta_i} J(\theta_t)

其中:

  • Gt,iG_{t,i} 是关于参数 θi\theta_i 的梯度平方和累积,到第 tt 次迭代时的值。
  • θiJ(θt)\nabla_{\theta_i} J(\theta_t) 是损失函数关于参数 θi\theta_i 的梯度。
  • η\eta 是全局学习率(初始学习率)。
  • ϵ\epsilon 是一个微小的常数(如 10810^{-8}),用于防止除以零。

原理解析

  • 自适应学习率Adagrad 通过累积每个参数的梯度平方和 Gt,iG_{t,i} 来缩放学习率。对于那些经常出现大梯度的参数,梯度平方和会增大,从而使得学习率变小;对于那些梯度较小或较少更新的参数,学习率相对较大。这种自适应性有助于更有效地更新不同尺度的参数。
  • 适合处理稀疏数据:在自然语言处理等稀疏特征的任务中,Adagrad 能够有效地调整学习率,提高训练效率。

Python 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

# 假设我们有一个需要优化的参数 theta
theta = np.zeros((n_parameters,)) # 参数向量
G = np.zeros_like(theta) # 累积梯度平方和

# 超参数设置
eta = 0.01 # 初始学习率
epsilon = 1e-8 # 防止除以零的微小常数
num_iterations = 1000 # 迭代次数

for t in range(1, num_iterations + 1):
grad = compute_gradient(theta) # 计算当前梯度,需要根据具体问题定义

# 累积梯度平方和
G += grad ** 2

# 更新参数
adjusted_learning_rate = eta / (np.sqrt(G) + epsilon)
theta = theta - adjusted_learning_rate * grad

在上述代码中:

  • compute_gradient(theta) 是一个函数,用于计算当前参数 theta 下的梯度。
  • G 是累积的梯度平方和,用于调整学习率。
  • 学习率会根据每个参数的梯度历史进行缩放,实现自适应。

Adadelta 算法

背景与动机

Adagrad 在训练过程中,学习率会不断地缩小,可能导致后期学习率过小,无法继续优化。Adadelta 是对 Adagrad 的改进版,通过限制累积梯度的窗口大小,解决了 Adagrad学习率不断衰减的问题。此外,Adadelta 还消除了对初始学习率 η\eta 的依赖。

数学公式

Adadelta 的参数更新规则:

  1. 梯度的指数加权平均(EWA):

E[g2]t=ρE[g2]t1+(1ρ)[θtJ(θt)]2E[g^2]_t = \rho E[g^2]_{t-1} + (1 - \rho) [\nabla_{\theta_t} J(\theta_t)]^2

  1. 计算参数更新量的期望平方:

E[Δθ2]t=ρE[Δθ2]t1+(1ρ)[Δθt]2E[\Delta \theta^2]_t = \rho E[\Delta \theta^2]_{t-1} + (1 - \rho) [\Delta \theta_t]^2

  1. 计算更新量:

Δθt=E[Δθ2]t1+ϵE[g2]t+ϵθtJ(θt)\Delta \theta_t = - \frac{\sqrt{E[\Delta \theta^2]_{t-1} + \epsilon}}{\sqrt{E[g^2]_t + \epsilon}} \nabla_{\theta_t} J(\theta_t)

  1. 更新参数:

θt+1=θt+Δθt\theta_{t+1} = \theta_t + \Delta \theta_t

其中:

  • E[g2]tE[g^2]_t 是梯度平方的指数加权平均。
  • E[Δθ2]tE[\Delta \theta^2]_t 是参数更新量平方的指数加权平均。
  • ρ\rho 是衰减系数,通常取值为 0.9。
  • ϵ\epsilon 是防止除以零的微小常数。

原理解析

  • 消除全局学习率依赖:Adadelta 通过计算参数更新量的期望值,消除了对全局学习率 η\eta 的依赖,实现了真正的自适应学习率。
  • 动态调整步长:通过梯度和参数更新量的历史信息,自适应地调整更新步长,避免学习率过大或过小的问题。

Python 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np

# 参数初始化
theta = np.zeros((n_parameters,))
E_grad = np.zeros_like(theta) # 梯度平方的指数加权平均
E_delta = np.zeros_like(theta) # 参数更新量平方的指数加权平均

# 超参数设置
rho = 0.95
epsilon = 1e-6
num_iterations = 1000

for t in range(1, num_iterations + 1):
grad = compute_gradient(theta) # 计算梯度

# 更新梯度平方的指数加权平均
E_grad = rho * E_grad + (1 - rho) * grad ** 2

# 计算参数更新量
delta_theta = - (np.sqrt(E_delta + epsilon) / np.sqrt(E_grad + epsilon)) * grad

# 更新参数
theta = theta + delta_theta

# 更新参数更新量平方的指数加权平均
E_delta = rho * E_delta + (1 - rho) * delta_theta ** 2

RMSProp 算法

背景与动机

RMSProp(Root Mean Square Propagation)是 Geoffrey Hinton 提出的,用于解决 Adagrad 学习率不断衰减的问题,与 Adadelta 类似。RMSProp 通过对累积梯度平方和进行指数加权平均,限制了累积历史数据的窗口大小,从而保持学习率的稳定。

数学公式

RMSProp 的参数更新规则:

  1. 梯度平方的指数加权平均:

E[g2]t=ρE[g2]t1+(1ρ)[θtJ(θt)]2E[g^2]_t = \rho E[g^2]_{t-1} + (1 - \rho) [\nabla_{\theta_t} J(\theta_t)]^2

  1. 更新参数:

θt+1=θtηE[g2]t+ϵθtJ(θt)\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} \nabla_{\theta_t} J(\theta_t)

其中:

  • E[g2]tE[g^2]_t 是梯度平方的指数加权平均。
  • η\eta 是全局学习率。
  • ρ\rho 是衰减系数,通常取值为 0.9。
  • ϵ\epsilon 是防止除以零的微小常数。

原理解析

  • 稳定学习率RMSProp 对梯度平方进行指数加权平均,避免了 Adagrad 中累积梯度平方和无限增大的问题,保持了学习率的稳定性。
  • 适用于非平稳目标:通过限制累积历史梯度的窗口大小,RMSProp 能够在非平稳目标中保持稳定的学习率。

Python 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

# 参数初始化
theta = np.zeros((n_parameters,))
E_grad = np.zeros_like(theta) # 梯度平方的指数加权平均

# 超参数设置
eta = 0.001 # 学习率
rho = 0.9
epsilon = 1e-8
num_iterations = 1000

for t in range(1, num_iterations + 1):
grad = compute_gradient(theta) # 计算梯度

# 更新梯度平方的指数加权平均
E_grad = rho * E_grad + (1 - rho) * grad ** 2

# 更新参数
theta = theta - (eta / (np.sqrt(E_grad) + epsilon)) * grad

优化算法的比较

算法 更新规则 特点
Adagrad θt+1=θtηGt+ϵθJ(θt)\theta_{t+1} = \theta_t - \dfrac{\eta}{\sqrt{G_t + \epsilon}} \nabla_\theta J(\theta_t) 自适应学习率,对稀疏数据效果好,但学习率不断衰减
Adadelta θt+1=θt+Δθt\theta_{t+1} = \theta_t + \Delta \theta_t,其中 Δθt\Delta \theta_t 的计算见上文 无需学习率参数,适应性强,解决了 Adagrad 的衰减问题
RMSProp θt+1=θtηE[g2]t+ϵθJ(θt)\theta_{t+1} = \theta_t - \dfrac{\eta}{\sqrt{E[g^2]_t + \epsilon}} \nabla_\theta J(\theta_t) 对梯度平方进行指数加权平均,稳定学习率,适用于非平稳目标

参数的选择与注意事项

  • 学习率 η\eta

    • 对于 Adagrad,η\eta 通常设置较小,如 0.01。
    • 对于 RMSProp,η\eta 通常设置为 0.001。
    • Adadelta 不需要指定全局学习率,这也是其优势之一。
  • 衰减系数 ρ\rho

    • 通常取值为 0.9 到 0.95。
    • ρ\rho 越大,表示对过去梯度的记忆越长。
  • ϵ\epsilon 的选择

    • 一般设置为 e6e^{-6}e8e^{-8},用于防止除以零。

总结

  • Adagrad:通过累积梯度平方和来适应每个参数的学习率,适合处理稀疏数据。然而,由于累积量不断增大,学习率会持续衰减,可能导致后期训练停滞。
  • Adadelta:对 Adagrad 的改进,通过使用梯度参数更新量指数加权平均,限制了累积窗口大小,避免了学习率过度衰减的问题,并且消除了对初始学习率的依赖。
  • RMSProp:与 Adadelta 类似,使用梯度平方的指数加权平均来调整学习率,保持了学习率的稳定性,适用于处理非平稳目标。

如果结合动量优化器RMSProp 的优势,就可以得到目前深度学习训练的高效而强大的默认选择优化器:Adam优化器,具体可参考:

Adam优化器
Adam优化器
在深度学习和机器学习的模型训练过程中,优化算法起着关键作用。 **Adam**(Adaptive Moment Estimation)优化器是目前最受欢迎和广泛使用的优化算法之一。它结合了`动量优化器`和 `RMSProp` 的优势,能够在训练过程中`自适应地调整学习率`,实现`高效`和`稳健`的梯度更新。 下面,我们将详细介绍 Adam 优化器的原理、数学公式,以及 Python 代码实现