当前位置: 首页 > backend >正文

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述

        Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通过累积历史梯度的平方信息,动态调整每个参数的学习率,使得频繁更新的参数学习率较小,稀疏更新的参数学习率较大。这种自适应特性使其在训练深度神经网络时表现优异,尤其在自然语言处理和推荐系统中广泛应用。

二.Adagrad的优缺点

        Adagrad的主要优势在于自适应学习率,尤其适合稀疏数据或非平稳目标的优化问题。其缺点在于累积的梯度平方会持续增长,导致后期学习率过小,可能过早停止训练。后续改进算法如RMSProp和Adam通过引入衰减机制解决了这一问题。尽管如此,Adagrad仍为自适应优化算法的发展奠定了基础。

三.算法原理与特性

3.1 基本核心思想

        自适应梯度算法(Adaptive Gradient Algorithm)通过累积历史梯度信息实现参数级学习率调整。其主要创新点在于:

$$g_{t,i} = \sum_{\tau=1}^t \nabla_\theta J(\theta_{\tau,i})^2$$

$$\theta_{t+1,i} = \theta_{t,i} - \frac{\eta}{\sqrt{g_{t,i} + \epsilon}} \nabla_\theta J(\theta_{t,i})$$

其中$$i$$表示参数索引,$$\eta$$为全局学习率, $$\epsilon$$为数值稳定常数(通常取 1e-8)

3.2 算法的特性

  • 参数级自适应:每个参数独立动态调整学习率,而不是固定学习率
  • 梯度敏感度:更新率较大的动态调整为较小的学习率,更新率较小的动态调整为较大的学习率
  • 累积记忆:通过历史梯度的平方和持续积累增长

3.3 更新规则

        Adagrad的更新公式基于参数的历史梯度信息,具体表现为对学习率的分母项进行累积。对于每个参数θᵢ,其更新规则如下:

# Adagrad更新公式
grad_squared += gradient ** 2
adjusted_lr = learning_rate / (sqrt(grad_squared) + epsilon)
theta -= adjusted_lr * gradient

        其中,grad_squared是梯度平方的累积,epsilon是为数值稳定性添加的常数,防止出现梯度为0导致分母变成无限大的情况,通常采用1e-8。Adagrad的累积特性使其对初始学习率的选择相对鲁棒,但长期训练可能导致学习率过小。

四、代码实现

4.1 测试函数设置

        使用非凸函数: f(x) = x**2 / 20.0 + y**2

4.2 收敛速度可视化

import numpy as np
from collections import OrderedDict
import matplotlib.pyplot as pltclass AdaGrad:"""AdaGrad"""def __init__(self, lr=1.5):self.lr = lrself.h = Nonedef update(self, params, grads):if self.h is None:self.h = {}for key, val in params.items():self.h[key] = np.zeros_like(val)for key in params.keys():self.h[key] += grads[key] * grads[key]params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)optimizers= AdaGrad()init_pos = (-7.0, 2.0)
params = {}
params['x'], params['y'] = init_pos[0], init_pos[1]
grads = {}
grads['x'], grads['y'] = 0, 0x_history = []
y_history = []def f(x, y):return x**2 / 20.0 + y**2def df(x, y):return x / 10.0, 2.0*yfor i in range(30):x_history.append(params['x'])y_history.append(params['y'])grads['x'], grads['y'] = df(params['x'], params['y'])optimizers.update(params, grads)x = np.arange(-10, 10, 0.01)
y = np.arange(-5, 5, 0.01)X, Y = np.meshgrid(x, y)
Z = f(X, Y)# for simple contour line
mask = Z > 7
Z[mask] = 0idx = 1# plot
plt.subplot(2, 2, idx)
idx += 1
plt.plot(x_history, y_history, 'o-', color="red")
plt.contour(X, Y, Z)
plt.ylim(-10, 10)
plt.xlim(-10, 10)
plt.plot(0, 0, '+')
# colorbar()
# spring()
plt.title("AdaGrad")
plt.xlabel("x")
plt.ylabel("y")plt.show()

        收敛效果如下:

五、Adagrad算法优缺点分析

5.1 优势特征

  1. 稀疏梯度优化:适合NLP等稀疏数据场景
  2. 自动学习率调整:减少超参调优成本
  3. 早期快速收敛:梯度累积未饱和时效率高

5.2 局限与改进

  1. 学习率单调衰减:后期更新停滞
  2. 内存消耗:需存储历史梯度平方和
  3. 梯度突变敏感:可能错过最优解

5.3 常用场景以及建议

  1. 推荐场景:自然语言处理、推荐系统
  2. 参数设置:
    • 初始学习率:0.01-0.1
    • 批量大小:128-512
  3. 配合技术:梯度裁剪+权重衰减

六. 各优化器对比

优化器收敛速度震荡幅度超参敏感性内存消耗
SGD
Momentum中等中等中等
Adagrad快(初期)
RMSProp稳定较小中等
Adam最快最小

七、全部优化器的对比代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cmdef test_function(x, y):return x ** 2 / 20.0 + y ** 2def compare_optimizers():# 初始化参数init_params = np.array([3.0, 4.0])epochs = 200optimizers = {'SGD': SGD(lr=0.1),'Momentum': Momentum(lr=0.1, momentum=0.9),'Adagrad': Adagrad(lr=0.1),'RMSProp': RMSProp(lr=0.001, decay=0.9),'Adam': Adam(lr=0.1, beta1=0.9, beta2=0.999)}# 训练过程plt.figure(figsize=(14,10))ax = plt.axes(projection='3d')X = np.linspace(-4, 4, 100)Y = np.linspace(-4, 4, 100)X, Y = np.meshgrid(X, Y)Z = test_function(X, Y)ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, alpha=0.6)for name, opt in optimizers.items():params = init_params.copy()trajectory = []for _ in range(epochs):grad = compute_gradient(params)params = opt.update(params, grad)trajectory.append(params.copy())trajectory = np.array(trajectory)ax.plot3D(trajectory[:,0], trajectory[:,1], test_function(trajectory[:,0], trajectory[:,1]), label=name, linewidth=2)ax.legend()ax.set_xlabel('x')ax.set_ylabel('y')ax.set_zlabel('z')plt.show()def compute_gradient(params):x, y = paramsdx = x / 10.0dy = 2.0*yreturn np.array([dx, dy])# 各优化器实现类
class SGD:def __init__(self, lr=0.01):self.lr = lrdef update(self, params, grads):return params - self.lr * gradsclass Momentum:def __init__(self, lr=0.01, momentum=0.9):self.lr = lrself.momentum = momentumself.v = Nonedef update(self, params, grads):if self.v is None:self.v = np.zeros_like(params)self.v = self.momentum*self.v + self.lr*gradsreturn params - self.vclass Adagrad:def __init__(self, lr=0.01, eps=1e-8):self.lr = lrself.eps = epsself.cache = Nonedef update(self, params, grads):if self.cache is None:self.cache = np.zeros_like(params)self.cache += grads**2return params - self.lr / (np.sqrt(self.cache) + self.eps) * gradsclass RMSProp:def __init__(self, lr=0.001, decay=0.9, eps=1e-8):self.lr = lrself.decay = decayself.eps = epsself.cache = Nonedef update(self, params, grads):if self.cache is None:self.cache = np.zeros_like(params)self.cache = self.decay*self.cache + (1-self.decay)*grads**2return params - self.lr / (np.sqrt(self.cache) + self.eps) * gradsclass Adam:def __init__(self, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.m = Noneself.v = Noneself.t = 0def update(self, params, grads):if self.m is None:self.m = np.zeros_like(params)self.v = np.zeros_like(params)self.t += 1self.m = self.beta1*self.m + (1-self.beta1)*gradsself.v = self.beta2*self.v + (1-self.beta2)*grads**2m_hat = self.m / (1 - self.beta1**self.t)v_hat = self.v / (1 - self.beta2**self.t)return params - self.lr * m_hat / (np.sqrt(v_hat) + self.eps)if __name__ == "__main__":compare_optimizers()

        效果图如下:

        观察图示可以得出以下结论:

  • Adagrad初期收敛速度明显快于SGD
  • 中后期被Adam、RMSProp超越
  • 在平坦区域表现出更稳定的更新方向
  • 对于陡峭方向能自动减小步长
http://www.xdnf.cn/news/12427.html

相关文章:

  • 超构光学与 AR 的深度融合 | 攻克 VAC 与眼动范围难题
  • DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
  • 完美搭建appium自动化环境
  • 解决Zotero翻译插件Zotero PDF Translate无法正常翻译
  • C# 快速检测 PDF 是否加密,并验证正确密码
  • Rust 通用代码生成器:莲花,红莲尝鲜版三十六,图片初始化功能介绍
  • 软件功能测试报告都包含哪些内容?
  • C语言三位数倒序输出(两种方法)
  • 使用xdocreport导出word
  • c++ map与multiset的介绍
  • JUnit​​ 和 ​​Mockito​​ 的详细说明及示例,涵盖核心概念、常用注解、测试场景和实战案例。
  • 集群与分布式与微服务
  • 软件测试:质量保障的基石与未来趋势
  • 计算机网络(6)——局域网
  • leetcode1971. 寻找图中是否存在路径-easy
  • 自托管图书搜索引擎Bookologia
  • EasyRTC嵌入式音视频通信SDK助力物联网/视频物联网音视频打造全场景应用
  • 6.6 day38
  • 现实生活例子[特殊字符] 通俗易懂的解释[特殊字符] JS中的原型和原型链[特殊字符]
  • AC68U刷梅林384/386版本后不能 降级回380,升降级解决办法
  • 一个WebRTC 分辨率动态爬升问题记录与解决过程
  • SQLServer中的存储过程与事务
  • Kafka 快速上手:安装部署与 HelloWorld 实践(二)
  • Kafka 快速上手:安装部署与 HelloWorld 实践(一)
  • uniapp 设置手机不息屏
  • Go 中 map 的双值检测写法详解
  • 从零实现STL哈希容器:unordered_map/unordered_set封装详解
  • Transformer-BiGRU多变量时序预测(Matlab完整源码和数据)
  • Python概率统计可视化——概率分布、假设检验与分子运动模型
  • GNSS终端授时方式-合集:PPS、B码、NTP、PTP、单站授时,共视授时