35.Adam算法

RMSProp 和 Adadelta 算法

在深度学习中,RMSProp 和 Adadelta 是两种常见的优化算法。它们都是在 AdaGrad 的基础上做了改进,以适应深度学习中的大规模参数优化需求。

RMSProp 算法

基本思想

RMSProp 对 AdaGrad 进行改进,通过引入衰减率来调整二阶动量的累积。这样可以避免 AdaGrad 中学习率过快减小的问题。

AdaGrad 的二阶动量计算公式如下:

\[ v_t = v_{t-1} + g_t^2 \]

而 RMSProp 采用了带有衰减率的计算方式:

\[ v_t = \beta v_{t-1} + (1 - \beta) g_t^2 \]

其中,\( \beta \) 是衰减率系数。

优缺点

优点:

  • 自动调整学习率,加速收敛速度。

  • 避免学习率过大或过小的问题。

  • 简单适用,适用于各种优化问题。

缺点:

  • 在处理稀疏特征时不够优秀。

  • 需要调整的超参数较多(衰减率 \( \beta \) 和学习率 \( \alpha \))。

  • 收敛速度可能不如某些更先进的优化算法。

代码实现

python 复制代码
import torch
import matplotlib.pyplot as plt

# 定义超参数
learning_rate = 0.01
epochs = 100
beta = 0.9

# 随机生成数据
x = torch.randn(100, 1)
y = 2 * x + 3 + torch.randn(100, 1) * 0.5

# 初始化参数
w = torch.randn(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# 定义RMSProp优化器
optimizer = torch.optim.RMSprop([w, b], lr=learning_rate, alpha=beta)

# 记录损失
losses = []

for epoch in range(epochs):
    # 预测
    y_pred = x * w + b
    # 计算损失
    loss = torch.mean((y_pred - y) ** 2)
    losses.append(loss.item())
    
    # 清空梯度
    optimizer.zero_grad()
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()

# 可视化训练过程
plt.plot(range(epochs), losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss with RMSProp')
plt.show()

Adadelta 算法

基本思想

Adadelta 是对 RMSProp 的进一步改进,旨在自动调整学习率,避免手动调参。它通过计算梯度和权重更新量的累积值来调整学习率,使得训练过程更加稳定。

Adadelta 的公式如下:

  1. 梯度的累积:

\[ E[g^2]t = \rho E[g^2]{t-1} + (1 - \rho) g_t^2 \]

  1. 权重更新量的累积:

\[ E[\Delta x^2]t = \rho E[\Delta x^2]{t-1} + (1 - \rho) (\Delta x_t)^2 \]

  1. 更新参数:

\[ \Delta x_t = -\frac{\sqrt{E[\Delta x^2]_{t-1} + \epsilon}}{\sqrt{E[g^2]_t + \epsilon}} g_t \]

\[ \theta_{t+1} = \theta_t + \Delta x_t \]

优缺点

优点:

  • 不需要手动调整学习率,节省调参时间。

  • 避免出现学习率饱和现象,使得训练更加稳定。

缺点:

  • 可能收敛较慢。

  • 需要维护梯度和权重更新量的累积值,增加了空间复杂度。

代码实现

python 复制代码
import torch
import matplotlib.pyplot as plt

# 定义超参数
learning_rate = 1.0  # Adadelta 不需要传统的学习率
epochs = 100
rho = 0.9
epsilon = 1e-6

# 随机生成数据
x = torch.randn(100, 1)
y = 2 * x + 3 + torch.randn(100, 1) * 0.5

# 初始化参数
w = torch.randn(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# 定义Adadelta优化器
optimizer = torch.optim.Adadelta([w, b], rho=rho, eps=epsilon)

# 记录损失
losses = []

for epoch in range(epochs):
    # 预测
    y_pred = x * w + b
    # 计算损失
    loss = torch.mean((y_pred - y) ** 2)
    losses.append(loss.item())
    
    # 清空梯度
    optimizer.zero_grad()
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()

# 可视化训练过程
plt.plot(range(epochs), losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss with Adadelta')
plt.show()

接下来,我们将介绍目前常用的梯度下降法中的王者------Adam算法。

Adam 算法

Adam(Adaptive Moment Estimation)是目前深度学习中最常用的优化算法之一。它结合了动量法和 RMSProp 的优点,通过计算一阶和二阶动量来动态调整学习率,具有较快的收敛速度和较高的稳定性。

基本思想

Adam 算法利用梯度的一阶动量(即梯度的指数加权平均)和梯度的二阶动量(即梯度平方的指数加权平均)来调整每个参数的学习率。具体公式如下:

  1. 梯度的一阶动量:

\[ m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t \]

  1. 梯度的二阶动量:

\[ v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 \]

  1. 偏差修正:

\[ \hat{m}_t = \frac{m_t}{1 - \beta_1^t} \]

\[ \hat{v}_t = \frac{v_t}{1 - \beta_2^t} \]

  1. 更新参数:

\[ \theta_{t+1} = \theta_t - \frac{\alpha \hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \]

其中:

  • \( \beta_1 \) 和 \( \beta_2 \) 分别是动量和均方根动量的衰减率,常用值为 \( \beta_1 = 0.9 \) 和 \( \beta_2 = 0.999 \)。

  • \( \epsilon \) 是一个很小的常数,用于防止分母为零,常用值为 \( 10^{-8} \)。

优缺点

优点

  • 自适应调整学习率,训练过程稳定,收敛速度快。

  • 能处理稀疏梯度,适用于大规模数据和参数。

  • 几乎不需要调整学习率等超参数。

缺点

  • 对于某些特定问题,可能会出现不稳定的收敛行为。

  • 参数调整多,超参数较多,调参复杂度高。

代码实现

python 复制代码
import torch
import matplotlib.pyplot as plt

# 定义超参数
learning_rate = 0.001
epochs = 100

# 随机生成数据
x = torch.randn(100, 1)
y = 2 * x + 3 + torch.randn(100, 1) * 0.5

# 初始化参数
w = torch.randn(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# 定义Adam优化器
optimizer = torch.optim.Adam([w, b], lr=learning_rate)

# 记录损失
losses = []

for epoch in range(epochs):
    # 预测
    y_pred = x * w + b
    # 计算损失
    loss = torch.mean((y_pred - y) ** 2)
    losses.append(loss.item())
    
    # 清空梯度
    optimizer.zero_grad()
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()

# 可视化训练过程
plt.plot(range(epochs), losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss with Adam')
plt.show()

小结

Adam 算法作为一种自适应的梯度下降优化算法,结合了动量法和 RMSProp 的优点,能够有效地加速模型的收敛,同时保持稳定性。它通过计算一阶和二阶动量来动态调整学习率,使得模型在训练过程中能够快速收敛,并适应不同的优化问题。尽管 Adam 需要调整的超参数较多,但其优越的性能使得它成为深度学习中最广泛使用的优化算法之一。

通过学习 Adam 算法,我们不仅掌握了一种先进的优化技术,还了解了深度学习中优化算法的发展历程和演进过程。希望大家能将这些知识应用到实际项目中,提升模型的性能和训练效率。

相关推荐
Ni-Guvara2 分钟前
函数对象笔记
c++·算法
泉崎26 分钟前
11.7比赛总结
数据结构·算法
你好helloworld28 分钟前
滑动窗口最大值
数据结构·算法·leetcode
AI街潜水的八角1 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple2 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少2 小时前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋3 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
咕咕吖3 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎4 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu4 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法