常见优化器详解

news2024/11/23 17:42:24

优化器

目前有两种主流优化器:随机梯度下降系(Stochastic Gradient Descent, SGD)和Adam系。

应该认识到的是,优化器并不是某类数学上的优化算法,而是梯度下降(一阶迭代法)的工程实现方案和包装。

1. 随机梯度下降系优化器

1.1 从完全梯度到随机梯度

这是最常用的一种优化器。它的思想非常巧妙。既保证了梯度下降的收敛性,又最大程度上保障了算法的时间复杂度。

先回顾一下经典的梯度下降算法公式:
θ t + 1 = θ t − α ∇ θ t L ( x , θ t ) T (1-1) θ_{t+1}=θ_t-α∇_{θ_t}L(x,θ_t )^T\tag{1-1} θt+1=θtαθtL(x,θt)T(1-1)
其中,α为学习率,L(x,θ)为损失函数。注意,L可以理解为关于输入数据x和模型参数θ向量的二元函数。对于自变量θ而言,随着输入x的变化,L(θ)其实着不同的函数!(L(x1,θ)、L(x2,θ)…)

那么考虑到训练集肯定不止1个输入数据,你觉得(1-1)在实际迭代训练时应该如何计算?最简单的想法是:为了保证计算到的梯度是使用了所有训练样本的信息,梯度应该取所有样本的梯度平均值。因此,式(1-1)更新如下:
θ t + 1 = θ t − α N ∇ θ t ∑ i = 1 N L ( x i , θ t ) T (1-2) θ_{t+1}=θ_t-\frac{α}{N} ∇_{θ_t}\sum^{N}_{i=1} L(x_i,θ_t)^T\tag{1-2} θt+1=θtNαθti=1NL(xi,θt)T(1-2)
(1-2)就是梯度下降算法在训练时的实现。**式中N为训练集样本数量。可以保证每次更新参数时都利用了所有样本的数据。但如果训练集的规模是1k、1w、100w呢??如果优化器按(1-2)设计,训练的时间明显会随数据集规模增大而增长。即,式(1-2)是一个O(n)时间的算法(n为数据集规模)。。。这肯定是没法用的!

怎么办呢?人们发现:如果每次更新参数时的梯度仅随机挑数据集中一个样本的梯度**(随机梯度)** 和 每次更新参数把所有样本的梯度取平均(完全梯度),这两种梯度的期望是一样的!也就是说,当模型在训练集上迭代的次数足够多时,完全可以用随机梯度来代替完全梯度。

于是,我们的式(1-2)就可以变为:
θ t + 1 = θ t − α ∇ θ t L ( x i , θ t ) T , x ∈ [ 1 , N ] (1-3) θ_{t+1}=θ_t-α∇_{θ_t}L(x_i,θ_t )^T,x\in[1,N]\tag{1-3} θt+1=θtαθtL(xi,θt)T,x[1,N](1-3)
(1-3)就是随机梯度下降法的实现。可见,当每次更新参数时,随机梯度下降在所有训练集中随机取一个样本计算梯度用来更新参数。随机梯度下降的时间复杂度是O(1)。

当然,有优点就有缺点。时间复杂度虽然降低了,但有三个问题:

  1. 并不一定快!
  2. 相比梯度下降更易受噪声数据影响。
  3. 对学习率的调整构成挑战。

下两节我们分别解释这三个问题,来引出随机梯度下降的两个改进实现。

1.2 批量随机梯度下降

第一点乍一看很难理解,为什么复杂度降低了实际运行还不一定快呢???这就需要你了解计算机工程的知识。

假设你的训练集规模是1w张图片,训练开始前你把他们都加载到了内存上,现在开始用梯度下降算法更新模型参数:

  1. CPU生成一个随机索引,需要计算索引图片的梯度,CPU向各级缓存寻址找这张图片。
  2. 发现缓存不命中,去内存里寻址。内存找到了图片并把图片给CPU各级缓存。
  3. CPU在缓存中计算该图像的梯度,更新参数。。。
  4. 重复步骤1-3 1w次,完成一次epoch。

这样列出来我们就不难发现随机梯度下降为什么不快了——时间浪费在步骤2。1w张图片进行1个epoch就要在内存中寻址1w次。换句话说,缓存命中率低。

那该怎么办?梯度下降一次计算所有数据的梯度时间复杂度高,随机梯度下降的缓存命中率又十分不佳…

没错,解决方案就是采取一种折中的方案,一次取一个batch的图片计算梯度平均,作为本次更新参数的依据:
θ t + 1 = θ t − α n ∇ θ t ∑ i = 1 n L ( x i , θ t ) T (1-4) θ_{t+1}=θ_t-\frac{α}{n} ∇_{θ_t}\sum^{n}_{i=1} L(x_i,θ_t)^T\tag{1-4} θt+1=θtnαθti=1nL(xi,θt)T(1-4)
**(1-4)就是批量梯度下降的实现。**式中n为深度学习中重要的超参数之一:batch_size。按(1-4)进行计算,理论上说一次epoch的内存寻址次数至少是原来的1/batch_size,缓存不命中次数大大降低,提高了梯度计算速度。
请添加图片描述
图1 目前为止三种梯度下降系算法的loss与达到时间对比

可见,sgd、b-sgd最终均可以和gd达到差不多的loss,这说明了随机梯度的方差确实和完全梯度一致(随机梯度是完全梯度的无偏估计)。但达到相同的loss,sgd甚至是最慢的。**而对于b-sgd,一定范围内,batch_size设置地越大,达到同样loss的时间越短。**这对我们选batch_size有一个很好的指示。

1.3 动量优化器

1.2节中的b-sgd方法可以解决很大一部分问题,不仅大大加快了训练速度,貌似也可以对噪声梯度有一定抑制作用。

但引入随机梯度后,学习率调整的问题对于一阶梯度 还无法解决,具体表现在两个方面:

  1. 对于同一参数的不同优化时期,优化效果不一致。
  2. 对于不同的参数,损失函数不同将导致优化效果不平衡。

先解释问题1:

在梯度下降算法中,由于每次更新几乎没有噪声梯度的干扰,训练结果可以自始至终向最优方向进发:
请添加图片描述
图2 gd方法在二元凸函数中的优化过程

但对于随机梯度下降:
请添加图片描述
图3 sgd方法在二元凸函数中的优化过程

可见,在随机梯度的影响下,优化如此简单的凸函数有时还会往反方向走(越到优化后期这个趋势越明显)。这种现象也不难理解,优化后期随着梯度减小,任何一个小的扰动都有会放大参数更新方向的误差。不幸的是,就算引入batch的概念,这种扰动带来的影响还是不容忽视,这咋整呢???

现在广泛采用的方法是:动态调整学习率(lr_scheduler),越到后期给越小的lr,以削弱后期噪声梯度带来的影响。各个深度学习框架封装好的学习率调度器都提供很多种学习率调整方法,详见:(4条消息) 史上最全学习率调整策略lr_scheduler_cwpeng.cn的博客-CSDN博客_学习率调整(Pytorch)

接下来看问题2:对于不同的参数,损失函数不同将导致优化效果不平衡。

啥意思呢,对于参数向量θ来说,不同的分量很可能会有差别很大的梯度分布,比如简单的二元凸函数:
f ( x 1 , x 2 ) = 0.1 x 1 2 + 9 x 2 2 f(x_1, x_2)=0.1x_1^2+9x_2^2 f(x1,x2)=0.1x12+9x22
在它身上应用gd系算法的效果:
请添加图片描述
图4 不同参数间梯度分布的不平衡问题

可见,x2分量梯度非常大,而x1分量梯度则很小。于是,应用gd系算法的效果就是:x2参数很快就能达到收敛,找到最优解;而x1分量迭代了好多好多步仍然没找到最优解,进而拉低了整个训练的效果。咋整???

动量优化器对这种问题的解法就是采用【历史平均梯度(动量)】来代替原来的梯度:
v t = β v t − 1 + g t θ t + 1 = θ t − α v t (1-5) v_t=βv_{t-1}+g_{t} \\ θ_{t+1}=θ_t-αv_t\tag{1-5} vt=βvt1+gtθt+1=θtαvt(1-5)
(1-5)就是动量优化器的实现。

式中gt是之前任意一种计算梯度(完全梯度、随机梯度、批量梯度…)

vt就是动量

β为动量参数(简称动量)

把动量的递推公式展开写就会发现,动量近似于把过去累积的梯度求平均。

用历史平均梯度更新参数(参考图4),如果梯度较大且在最优点附近震荡(图4中x2),历史平均梯度则会相互抵消好多,可以正常收敛;而对于梯度较小的情况(图4中x1), 用历史梯度正好可以累积更大的梯度,让其加速收敛。总之,这是一种对各个参数不同梯度分布情况可以较好自适应的算法。
请添加图片描述
图5 使用动量优化器对于梯度不平衡问题的自适应效果

可见,用了动量之后,x1确实比图4收敛更快,从而总体达到更快的收敛效果。

1.4 小节

以上就是SGD优化器的全部内容了。**(1-5)式可以给产品级框架使用的SGD优化器一个完整的概述。**是否使用动量、动量参数取值、batch_size的取值、lr的取值、lr_scheduler的选取,都是便于插拔使用的。

from torch.optim import SGD
from torch.optim import lr_scheduler


optimizer = SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler=lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

2. Adam系优化器

SGD大部分情况下可以很好地解决大部分优化问题。Adam系优化器试图利用历史梯度信息对学习率做一些自适应的处理。

2.1 AdaGrad

AdaGrad认为,当前梯度大,说明当前处于优化早期阶段,此时模型获得的信息过少,不应该走的太快,应该对学习率做一个较大的惩罚;而梯度小时,说明优化已经进入后期,此时模型应该已经获得更多信息了,不应该对学习率做更大的惩罚了(但后期仍应该让lr处于下降的趋势)。

基于这种想法,他设计了如下的更新公式:
s t = s t − 1 + g t 2 θ t = θ t − 1 − α s t + ε . g t (2-1) s_t=s_{t-1}+g_t^2 \\ θ_{t}=θ_{t-1}-\frac{α}{\sqrt{s_t+\varepsilon}}. g_t\tag{2-1} st=st1+gt2θt=θt1st+ε α.gt(2-1)
**(2-1)就是AdaGrad的实现。**可以看到,随着优化进程进行,gt应该会逐渐变小,因此对学习率的惩罚【涨幅】会越来越小(学习率会一直下降,但下降得越来越慢)。

2.2 RMSProp

上面的AdaGrad有一个问题,就是在优化后期时,学习率由于持续受到惩罚,变得非常小,不咋动了…原因在于长时间积累的梯度过大。所以RMSProp对学习率惩罚st的积累做出约束:
s t = γ s t − 1 + ( 1 − γ ) g t 2 θ t = θ t − 1 − α s t + ε . g t (2-2) s_t=\gamma s_{t-1}+(1-\gamma)g_t^2 \\ θ_{t}=θ_{t-1}-\frac{α}{\sqrt{s_t+\varepsilon}}. g_t\tag{2-2} st=γst1+(1γ)gt2θt=θt1st+ε α.gt(2-2)
**(2-2)就是RMSProp的实现。**γ一般取一个较大的值(0.9),这样每代叠加的惩罚就会比较小。到后期仍保持健康的学习率。
请添加图片描述
图6 AdaGrad在二元凸函数上的优化表现(α=0.4)
请添加图片描述
图7 RMSProp在二元凸函数上的优化表现(α=0.4,γ=0.9)

对比可见,在同样的学习率下,RMSProp在后期确实具有更大的学习率。

2.3 Adam

Adam是一种结合了前面几种(包括SGD中的一些)方法的一种综合实现,主要包括动量、自适应梯度惩罚:
v t = β 1 v t − 1 + ( 1 − β 1 ) g t s t = β 2 s t − 1 + ( 1 − β 2 ) g t 2 v t ^ = v t 1 − β 1 s t ^ = s t 1 − β 2 θ t = θ t − 1 − α v t ^ s t ^ + ε . g t (2-3) v_t=\beta_1 v_{t-1}+(1-\beta_1)g_t\\ s_t=\beta_2 s_{t-1}+(1-\beta_2)g_t^2 \\ \widehat{v_t}=\frac{v_t}{1-\beta_1}\\ \widehat{s_t}=\frac{s_t}{1-\beta_2}\\ θ_{t}=θ_{t-1}-\frac{α\widehat{v_t}}{\sqrt{\widehat{s_t}}+\varepsilon}. g_t\tag{2-3} vt=β1vt1+(1β1)gtst=β2st1+(1β2)gt2vt =1β1vtst =1β2stθt=θt1st +εαvt .gt(2-3)
**(2-3)就是Adam的实现。**看似有些复杂,不过仔细一看都很熟悉。第一行的动量在前面的基础上稍作系数上的改动,第二行的自适应梯度和RMSProp一样的,第三第四行是对vt和st的一个标准化,最后用【类似于】AdaGrad的方式对学习率做自适应惩罚。但是注意根号的范围,和AdaGrad的区别是不包括后面那个epsilon。

这样看,Adam的设计思想就比较清晰了,大致可以看成是引入动量的RMSProp。

2.4 小节

总得来说,Adam和SGD系的主要区别在于引入对学习率的自适应惩罚,可以根据历史梯度信息自适应调整(减小)学习率。

在使用时,SGD一般还需要引入lr_scheduler来调度学习率,但Adam自带学习率惩罚显然就没必要了,可见还是使用Adam更省心一些啊。(但我咋感觉还是SGD用得更多?)

最后要注意的是,使用Adam时,weight decay并不是传统意义上参数的L2范数正则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VALSE2023-内容总结(正在更新)

博文为精选内容,完整ppt请留言索取 一周内更新完毕,敬请期待 2023年度视觉与学习青年学者研讨会 (Vision And Learning SEminar, VALSE)于6月10日至12日在无锡太湖国际博览中心召开,由中国人工智能学会、中国图象图形学学会主办,…

Transformer与注意力机制

Transformer与注意力机制 1. RNN基础 循环神经网络(RNN)是专门用来处理自然语言、金融信息等时序数据的一种神经网络。它的结构和运作方式如下图所示,基于马尔可夫决策模型。 图1 循环神经网络的结构和运作方式 应该注意到以下几个性质&a…

周四见 | 物流人的一周资讯

菜鸟618推出“小件3元发全国”服务 6月12日消息,针对美妆商家618期间轻小件的发货需求,菜鸟推出“极致小件3元发全国”服务,利用全国6大基地,100%自营的仓配供应链能力,支持订单高爆发,并提供破损包赔、时…

开源、跨平台安卓摸鱼(投屏)软件 Scrcpy 中文使用指南

废话不说,先上链接:GitHub上的Scrcpy 介绍: Scrcpy 可以将手机画面投射到电脑上,让你可以在电脑上对手机进行操控。Scrcpy 通过 USB 或 Wi-Fi 与安卓手机相连,不需要在手机上安装任何 app,也不需要取得 R…

Vue-插件(plugin)

插件(plugin) 插件是vue中特别强大并且特别简单的一个东西,它可以帮助我们增强vue 插件本质来说就是一个对象,但是这个对象必须包含install(安装)方法,由vue帮助我们调用 只要插件写的足够的好,就可以帮助我们实现很多的功能&a…

一些常用linux命令

系列文章目录 文章目录 系列文章目录一、常用linux命令1. lsof介绍2.查看进程的几种命令3.查看inode号的几种命令4.查看Linux系统负载的命令一般常用的有4种:5.iostat 主要用于输出磁盘IO 和 CPU的统计信息。 总结 一、常用linux命令 1. lsof介绍 lsof可以查看你所打开的文件…

工具篇--5 WIndow/Linux--Mysql binLog日志监听Canal安装

前言:作为一个中间件canal,可以实时的监听到mysql 中表结构及数据的变化, 项目中只需要接入canal ,不需要我们在业务中进行aop 或者接口的编写就可以及时的收到数据的变化。 1 介绍: Canal是阿里巴巴开源的一款基于M…

想要用好ChatGPT,首先得学会用提示词!

用好ChatGPT,可以辅助学习~ 期末季,一年中体验过最多地区时差的一段时期,懂的都懂😲 放下essay刷个小红薯也都是“赶due病友”…几周内5-6个essay ddl的经历相信不少同学都深有体会。 而今年的一大不同就是有了“哆啦C梦”——…

PostgreSQL行转列

管理拓展 启用拓展 -- 启用拓展 create extension tablefunc; --tablefunc扩展模块包含一系列返回记录表的函数。 create extension "uuid-ossp";--uuid扩展函数拓展启动后,可以在public空间下查看到crosstab函数 卸载函数 drop extension tablefunc…

信创办公–基于WPS的PPT最佳实践系列 (使用母版进行有效设计)

信创办公–基于WPS的PPT最佳实践系列 (使用母版进行有效设计) 目录 应用背景相关知识操作步骤1、认识母版2、在每页幻灯片底部添加logo图片3、第一张幻灯片和最后一张幻灯片出现logo图片,其他页面不出现4、除了封面封底之外,其他页…

硬件速攻-ATK1218正点原子GPS模块

效果演示(注意室内是没有数据) 模块实物图与接线方法 SPP 可不接(这个连到了模块上的灯) RXD 接单片机TXD TXD 接单片机串口RXD GND 接单片机GND VCC接单片机5V IPEX一定要接送的天线 而且天线要放到室外 再次说明提醒 精简代码与说明 如果你只想获取经纬度而已 你可用屏…

原来C语言计算的数只要低过4个字节就要整型提升!

C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换被称为整型提升。 比如: char a 3; char b 127; char c a b; printf("%d&q…

Vue中如何进行地图轨迹展示与追踪?

Vue中如何进行地图轨迹展示与追踪? 随着移动互联网技术的快速发展,位置数据的应用越来越广泛。在许多应用程序中,地图轨迹展示和追踪功能已经成为了基本功能之一。在Vue中,我们可以使用许多不同的地图API和库来实现这些功能。本文…

ATTCK v13版本战术介绍——凭证访问(三)

一、引言 在前几期文章中我们介绍了ATT&CK中侦察、资源开发、初始访问、执行、持久化、提权、防御规避战术,本期我们为大家介绍ATT&CK 14项战术中凭证访问战术第13-17种子技术,后续会介绍凭证访问其他子技术,敬请关注。 二、ATT&…

智能图像处理竟然能做出这种神奇的事

前言 大家都知道,搞论文的时候很多的时候都需要数据来做支撑,对应的我就需要在很多期刊中获取对应的Figure,但是获取很麻烦,就算拍摄出来,放在论文里面效果也不是很好,而且歪七扭八的很碍眼。在这种事情上就…

5.3图的综合应用算法(最小生成树、最短路径生成)

一.最小生成树算法 1.概念(Minimum-Spanning-Tree)MST 生成树:针对于连通图,包含全部顶点,去掉一条边后不连通,加一条边形成环 最小生成树:带权连通无向图,边的权值之和最小的生成树(MST) 2.…

关于前端跨域的结局方案

前言 跨域产生的原因 浏览期的安全策略。常见的解决跨域的方法&#xff1a; 1.JONSP 利用<script>标签的src可以发起跨域请求,大致过程&#xff1a;前端的方法名传到地址上callbackxx 缺点&#xff1a;只能get方法2.domain.iframe、domain.hash、domain.parent等 上述这…

VUE项目无法启动NODE版本与NODE-SASS、SASS-LOADER版本不兼容

系列文章目录 文章目录 系列文章目录错误分析一、版本比对二、解决方案总结 错误分析 在VUE项目开发中&#xff0c;我们经常会遇到报错&#xff1a; Node Sass version 7.0.1 is incompatible with ^4.0.0。 网上解决方案也千奇百怪&#xff0c;最终操作下来&#xff0c;也是…

首添机密计算创新成果!龙蜥首获 ACM SIGSOFT 杰出论文奖

近日&#xff0c;软件工程领域的全球旗舰级会议-软件工程大会 ICSE 在澳大利亚墨尔本市召开&#xff0c;龙蜥社区云原生机密计算 SIG 核心成员&#xff08;阿里云JVM 团队&#xff09;在 Java 机密计算方面的研究成果入选了 ICSE2023&#xff0c;并且以该会议今年唯一的 All Fi…

STM32F407之SD卡读数据介绍

1&#xff0c;SD卡基础知识 SD卡&#xff08;Secure Digital Memory Card&#xff09;即&#xff1a;安全数字存储卡&#xff0c;它是在MMC的基础上发展而来&#xff0c;作为存储器件广泛应用于电子产品中。 1.1 SD卡有SDIO和SPI两种传输方式&#xff0c;具体信号定义如下&…