Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad

2023-10-27

目录

写在前面

一、 torch.optim.SGD 随机梯度下降

SGD代码

SGD算法解析

1.MBGD(Mini-batch Gradient Descent)小批量梯度下降法

 2.Momentum动量

3.NAG(Nesterov accelerated gradient)

SGD总结

二、torch.optim.ASGD随机平均梯度下降

三、torch.optim.Rprop

四、torch.optim.Adagrad 自适应梯度

Adagrad 代码

Adagrad 算法解析

AdaGrad总结


优化器系列文章列表

Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad

Pytorch优化器全总结(二)Adadelta、RMSprop、Adam、Adamax、AdamW、NAdam、SparseAdam

Pytorch优化器全总结(三)牛顿法、BFGS、L-BFGS 含代码

Pytorch优化器全总结(四)常用优化器性能对比 含代码

写在前面

        优化器时深度学习中的重要组件,在深度学习中有举足轻重的地位。在实际开发中我们并不用亲手实现一个优化器,很多框架都帮我们实现好了,但如果不明白各个优化器的特点,就很难选择适合自己任务的优化器。接下来我会开一个系列,以Pytorch为例,介绍所有主流的优化器,如果都搞明白了,对优化器算法的掌握也就差不多了。

        作为系列的第一篇文章,本文介绍Pytorch中的SGD、ASGD、Rprop、Adagrad,其中主要介绍SGD和Adagrad。因为这四个优化器出现的比较早,都存在一些硬伤,而作为现在主流优化器的基础又跳不过,所以作为开端吧。

        我们定义一个通用的思路框架,方便在后面理解各算法之间的关系和改进。首先定义待优化参数 \theta,目标函数J(\theta ),学习率为 \eta ,然后我们进行迭代优化,假设当前的epoch为t,参数更新步骤如下:

1. 计算目标函数关于当前参数的梯度: 

g_{t}=\bigtriangledown J(\theta _{t-1})                               (1)

 2. 根据历史梯度计算一阶动量和二阶动量:

m_{t}=\phi (g_{1},g_{2}...,g_{t})                (2)

v_{t}=\varphi (g_{1},g_{2}...,g_{t})                 (3)

 3. 计算当前时刻的下降梯度: 

\bigtriangleup _{\theta }=\eta *\frac{m_{t}}{\sqrt{v_{t}}}                           (4)

4. 根据下降梯度进行更新:  

 \theta _{t}=\theta _{t-1}-\bigtriangleup _{\theta}                       (5)

        下面介绍的所有优化算法基本都能套用这个流程,只是式子(4)的形式会有变化。

一、 torch.optim.SGD 随机梯度下降

        该类可实现 SGD 优化算法,带动量 的SGD 优化算法和带 NAG(Nesterov accelerated gradient)的 SGD 优化算法,并且均可拥有 weight_decay(权重衰减) 项。

SGD代码

'''
params(iterable)- 参数组,优化器要优化的那部分参数。
lr(float)- 初始学习率,可按需随着训练过程不断调整学习率。
momentum(float)- 动量,通常设置为 0.9,0.8
dampening(float)- dampening for momentum ,暂时不了其功能,在源码中是这样用的:buf.mul_(momentum).add_(1 - dampening, d_p),值得注意的是,若采用nesterov,dampening 必须为 0.
weight_decay(float)- 权值衰减系数,也就是 L2 正则项的系数
nesterov(bool)- bool 选项,是否使用 NAG(Nesterov accelerated gradient)
'''
class torch.optim.SGD(params, lr=<object object>, momentum=0, dampening=0, weight_decay=0, nesterov=False)

SGD算法解析

1.MBGD(Mini-batch Gradient Descent)小批量梯度下降法

        明明类名是SGD,为什么介绍MBGD呢,因为在Pytorch中,torch.optim.SGD其实是实现的MBGD,要想使用SGD,只要将batch_size设成1就行了。

        MBGD就是结合BGD和SGD的折中,对于含有 n个训练样本的数据集,每次参数更新,选择一个大小为 m(m<n) 的mini-batch数据样本计算其梯度,其参数更新公式如下,其中j是一个batch的开始:

\theta _{t}=\theta _{t-1}-\eta *\frac{1}{m}*\sum_{i=j}^{i=j+m-1}\bigtriangledown _{\theta _{i}}J_{i}(\theta _{t-1})                (6)

优点:使用mini-batch的时候,可以收敛得很快,有一定摆脱局部最优的能力。

缺点:a.在随机选择梯度的同时会引入噪声,使得权值更新的方向不一定正确

           b.不能解决局部最优解的问题

 2.Momentum动量

         动量是一种有助于在相关方向上加速SGD并抑制振荡的方法,通过将当前梯度与过去梯度加权平均,来获取即将更新的梯度。如下图b图所示。它通过将过去时间步长的更新向量的一小部分添加到当前更新向量来实现这一点:

image-20211126212003953

 动量项通常设置为0.9或类似值。

参数更新公式如下,其中ρ 是动量衰减率,m是速率(即一阶动量)

g_{t}=\bigtriangledown_\theta J(\theta _{t-1})                         (7)

m_{t} = \rho *m_{t-1} +g_{t}                (8)

\theta _{t}=\theta _{t-1}-\eta *m_{t}                   (9)

3.NAG(Nesterov accelerated gradient)

        NAG的思想是在动量法的基础上展开的。动量法是思想是,将当前梯度与过去梯度加权平均,来获取即将更新的梯度。在知道梯度之后,更新自变量到新的位置。也就是说我们其实在每一步,是知道下一时刻位置的。这时Nesterov就说了:那既然这样的话,我们何不直接采用下一时刻的梯度来和上一时刻梯度进行加权平均呢?下面两张图看明白,就理解NAG了:

        这里写图片描述

 无

NAG和经典动量法的差别就在B点和C点梯度的不同。 

 参数更新公式:

g_{t}=\bigtriangledown_\theta J(\theta _{t}-\rho m_{t-1})                (10)

m_{t} = \rho *m_{t-1} +g_{t}                        (11)

\theta _{t}=\theta _{t-1}-\eta *m_{t}                           (12)

        上式中的-\rho m_{t-1}就是图中的B到C那一段向量,\theta _{t}-\rho m_{t-1}就是C点坐标(参数)。可以看到NAG除了式子(10)与式子(7)有所不同,其余公式和Momentum是一样的。

        一般情况下NAG方法相比Momentum收敛速度快、波动也小。实际上NAG方法用到了二阶信息,所以才会有这么好的结果。

         Nesterov动量梯度的计算在模型参数施加当前速度之后,因此可以理解为往标准动量中添加了一个校正因子。在凸批量梯度的情况下,Nesterov动量将额外误差收敛率从O(\frac{1}{k})(k步后)改进到  O(\frac{1}{k^2}),然而,在随机梯度情况下,Nesterov动量对收敛率的作用却不是很大。

SGD总结

使用了Momentum或NAG的MBGD有如下特点:

优点:加快收敛速度,有一定摆脱局部最优的能力,一定程度上缓解了没有动量的时候的问题

缺点:a.仍然继承了一部分SGD的缺点

          b.在随机梯度情况下,NAG对收敛率的作用不是很大

          c.Momentum和NAG都是为了使梯度更新更灵活。但是人工设计的学习率总是有些生硬,下面介绍几种自适应学习率的方法。

推荐程度:带Momentum的torch.optim.SGD 可以一试。

二、torch.optim.ASGD随机平均梯度下降

        ASGD 也称为 SAG,表示随机平均梯度下降(Averaged Stochastic Gradient Descent),简单地说 ASGD 就是用空间换时间的一种 SGD,因为很少使用,所以不详细介绍,详情可参看论文: http://riejohnson.com/rie/stograd_nips.pdf

'''
params(iterable)- 参数组,优化器要优化的那些参数。
lr(float)- 初始学习率,可按需随着训练过程不断调整学习率。
lambd(float)- 衰减项,默认值 1e-4。
alpha(float)- power for eta update ,默认值 0.75。
t0(float)- point at which to start averaging,默认值 1e6。
weight_decay(float)- 权值衰减系数,也就是 L2 正则项的系数。
'''
class torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)

 推荐程度:不常见

三、torch.optim.Rprop

        该类实现 Rprop 优化方法(弹性反向传播),适用于 full-batch,不适用于 mini-batch,因而在 mini-batch 大行其道的时代里,很少见到。

'''
params - 参数组,优化器要优化的那些参数。
lr - 学习率
etas (Tuple[float, float])- 乘法增减因子
step_sizes (Tuple[float, float]) - 允许的最小和最大步长
'''
class torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))

优点:它可以自动调节学习率,不需要人为调节

缺点:仍依赖于人工设置一个全局学习率,随着迭代次数增多,学习率会越来越小,最终会趋近于0

推荐程度:不推荐

四、torch.optim.Adagrad 自适应梯度

        该类可实现 Adagrad 优化方法(Adaptive Gradient),Adagrad 是一种自适应优化方法,是自适应的为各个参数分配不同的学习率。这个学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。

Adagrad 代码

'''
params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
lr (float, 可选) – 学习率(默认: 1e-2)
lr_decay (float, 可选) – 学习率衰减(默认: 0)
weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)
initial_accumulator_value - 累加器的起始值,必须为正。

'''
class torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)

Adagrad 算法解析

        AdaGrad对学习率进行了一个约束,对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些。这样大大提高梯度下降的鲁棒性而该方法中开始使用二阶动量,才意味着“自适应学习率”优化算法时代的到来。
        在SGD中,我们每次迭代对所有参数进行更新,因为每个参数使用相同的学习率。而AdaGrad在每个时间步长对每个参数使用不同的学习率。AdaGrad消除了手动调整学习率的需要。AdaGrad在迭代过程中不断调整学习率,并让目标函数中的每个参数都分别拥有自己的学习率。大多数实现使用学习率默认值为0.01,开始设置一个较大的学习率。

        AdaGrad引入了二阶动量。二阶动量是迄今为止所有梯度值的平方和,即v_{t}=\sum_{i=1}^{t}g_{t}^{2}它是用来度量历史更新频率的。也就是说,我们的学习率现在是\frac{\eta }{\sqrt{v_{t}+\epsilon }},从这里我们就会发现 \sqrt{v_{t}+\epsilon }是恒大于0的,而且参数更新越频繁,二阶动量越大,学习率就越小,这一方法在稀疏数据场景下表现非常好,参数更新公式如下: 

        v_{t}=\sum_{i=1}^{t}g_{t}^{2}                                                    (13)

        \theta _{t}=\theta _{t-1}-\eta *\frac{g_{t}}{\sqrt{v_{t}+\epsilon }}                        (14)

AdaGrad总结

        AdaGrad在每个时间步长对每个参数使用不同的学习率。并且引入了二阶动量,二阶动量是迄今为止所有梯度值的平方和。

优点:AdaGrad消除了手动调整学习率的需要。AdaGrad在迭代过程中不断调整学习率,并让目标函数中的每个参数都分别拥有自己的学习率。

缺点:a.仍需要手工设置一个全局学习率  , 如果  设置过大的话,会使regularizer过于敏感,对梯度的调节太大

        b.在分母中累积平方梯度,由于每个添加项都是正数,因此在训练过程中累积和不断增长。这导致学习率不断变小并最终变得无限小,此时算法不再能够获得额外的知识即导致模型不会再次学习。

 推荐程度:不推荐

优化器系列文章列表

Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad

Pytorch优化器全总结(二)Adadelta、RMSprop、Adam、Adamax、AdamW、NAdam、SparseAdam

Pytorch优化器全总结(三)牛顿法、BFGS、L-BFGS 含代码

Pytorch优化器全总结(四)常用优化器性能对比 含代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad 的相关文章

随机推荐

  • 虚拟化存储技术

    文章目录 前言 一 HCLA存储技术趋势与智能存储组件 1 HCLA存储技术趋势 1 什么是数据存储 2 数据存储系统 3 数据分类 4 数据存储发展趋势 小结 2 智能存储组件 控制框 硬盘框 级联模块 硬盘 接口模块 二 虚拟化与网络存
  • C++的std::for_each()

    当给定一个容器范围 我们通常需要对其中的每个元素执行相同的操作 这样的操作可能包括打印元素 修改元素的值或应用一个自定义函数等等 在 C 标准库中 std for each 算法函数提供了一种方便的方式来对容器范围内的元素执行指定的操作 s
  • Golang空结构体struct{}的作用是什么?

    文章目录 占位符 通道标识 键集合 内存占用优化 总结 在Go语言中 空结构体 struct 是一种特殊的数据类型 它不占用任何内存空间 空结构体没有任何字段 也没有任何方法 尽管它看起来没有实际的用途 但在编程中确实有一些常见的应用场景
  • Handler dispatch failed; nested exception is java.lang.NoSuchMethodError

    一 问题描述 1 报错 org springframework web util NestedServletException Handler dispatch failed nested exception is java lang No
  • 清华智能体宇宙火了,AI模拟“囚徒困境”等实验只需几行简单配置

    丰色 发自 凹非寺量子位 公众号 QbitAI 可以轻松模拟社会实验的多智能体宇宙来了 它由清华大学联合北邮 微信团队推出 目前已在GitHub揽获1 1k标星 名字简单粗暴 就叫 AgentVerse 划重点 这个环境专门针对大语言模型开
  • 蓝桥杯试题 入门训练 Fibonacci数列 C、C++

    蓝桥杯试题 入门训练 Fibonacci数列 C C 问题描述 Fibonacci数列的递推公式为 Fn Fn 1 Fn 2 其中F1 F2 1 当n比较大时 Fn也非常大 现在我们想知道 Fn除以10007的余数是多少 输入格式 输入包含
  • SpringBoot 日志信息输出

    今天启动SpringBoot项目发现 大于许多日志信息 但是大部分提示是 那些注解类没有被使用 日志输出信息如下 CodecsAutoConfiguration matched ConditionalOnClass found requir
  • [echarts]横向柱状图的两种简便画法

    示例图 第一种方法 可以随意控制y左轴和y右轴的显示位置 let option 柱状图的位置 grid left 0 right 0 bottom 0 top 0 containLabel false 图表两侧是否留白 dataZoom t
  • [ C++ ] — 结构体和共用体

    一 C 中的结构体 1 声明 声明的过程不分配内存 struct Box char name 10 double length double width double height 声明的同时实例化 实例化要分配内存 struct Box
  • 磁盘性能指标—IOPS、吞吐量及测试

    磁盘性能指标 IOPS 吞吐量及测试 IOPS 吞吐量 磁盘服务时间 最大IOPS的理论计算方法 IOPS Input Output Per Second 即每秒的输入输出量 或读写次数 是衡量磁盘性能的主要指标之一 IOPS是指单位时间内
  • 算法设计与分析(第二版)上机实验题——C语言实现

    算法设计与分析 第一章 实验1 统计求最大 最小元素的平均比较次数 实验2 求无序序列中第k小的元素 实验3 出队第k个元素 实验4 设计一种好的数据结构 实验5 设计一种好的数据结构 第二章 实验1 逆置单链表 实验2 判断两棵二叉树是否
  • window onresize事件注意一下效率问题

    最近好久没有发帖了 今天在写 vue 项目的时候 echarts 图标需要随着 窗口变化适配 在使用 onresize 的时候 延时器代码不会写了 这里再记录下 代码如下 mounted 添加 echarts 窗口变化 事件 side me
  • STM32的“GPU”——DMA2D实例详解

    来源 本文由RT Thread社区成员梦千年撰写 点击文末阅读原文可查看出处 前言 GPU即图形处理器 是现代显卡的核心 在没有GPU的时代 所有图形的绘制都是由CPU来完成的 CPU需要计算图形的边界 颜色等数据 并且负责将数据写入显存
  • STM32中断清除标志位后无法再次进入中断问题及解决方案

    USART清除中断标志位问题 在调用USART ClearITPendingBit 函数清除中断标志位的时候 会导致下一次中断无法进入 例如以下程序 错误案例 void USART1 IRQHandler if USART GetITSta
  • 001:goodcopy

    编写GoodCopy类模板 使得程序按指定方式输出 include using namespace std template struct GoodCopy 在此处补充你的代码 int a 200 int b 200 string c 20
  • Air Playit - 直接在手机上通过WiFi无线播放电脑上的海量高清电影视频 (免费跨平台看片神器)

    http www iplaysoft com airplayit html 很多人都会下载一些电视剧 电影等视频放在电脑上 然而 有时别人在用你电脑或自己懒懒地躺在沙发上的时候 却想着要是能直接在手机上无线播放电脑上的电影视频MV神马的那该
  • 【老生谈算法】matlab实现图像插值与几何变换算法——几何变换算法

    Matlab实现图像几何变换与插值 1 文档下载 本算法已经整理成文档如下 有需要的朋友可以点击进行下载 说明 文档 点击下载 本算法文档 老生谈算法 matlab实现图像插值与几何变换算法 doc 更多matlab算法原理及源码详解可点击
  • 第65步 时间序列建模实战:ARIMA建模(Eviews)

    基于WIN10的64位系统演示 一 写在前面 从这一期开始 我们开始入坑时间序列模型 时间序列是一种数据类型 其中的数据点是按照时间顺序排列的 这种数据类型常常出现在各个领域 比如金融 股票价格的历史变动 气象 过去几年的天气状况 医学 一
  • rdesktop连接windows主机提示被拒绝的解决方法

    1 在待连接的Windows主机上依次 右击 我的电脑 gt 属性 gt 高级系统设置 gt 远程设置 gt 在远程桌面选项中 选择允许运行任意版本远程桌面的连接 2 检查linux主机和待连接的Windows 主机是否可以相互ping通
  • Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad

    目录 写在前面 一 torch optim SGD 随机梯度下降 SGD代码 SGD算法解析 1 MBGD Mini batch Gradient Descent 小批量梯度下降法 2 Momentum动量 3 NAG Nesterov a