| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> 深度学习之梯度下降与优化 -> 正文阅读 |
|
[人工智能]深度学习之梯度下降与优化 |
参考 pytorch学习系列(4):常用优化算法_ch ur h的博客深度学习各类优化器详解(动量、NAG、adam、Adagrad、adadelta、RMSprop、adaMax、Nadam、AMSGrad)_恩泽君的博客-CSDN博客pytorch学习系列(4):常用优化算法_ch ur h的博客-CSDN博客 一、问题的提出大多数机器学习或者深度学习算法都涉及某种形式的优化。 优化指的是改变 以最小化或最大化某个函数 的任务。 我们通常以最小化 指代大多数最优化问题。 其中 然后要使得最小化它。 θ表示X映射成Y的权重,x表示一次特征。假设x0=1,上式就可以写成: 分别使用表示第J个样本。我们计算的目的是为了让计算的值无限接近真实值y,即代价函数可以采用LMS算法 要获取J(θ)最小,即对J(θ)进行求导且为零: 总之,梯度下降是另一种优化的不错方式,比直接求导好很多。 二、梯度下降梯度下降:我们知道曲面上方向导数的最大值的方向就代表了梯度的方向,因此我们在做梯度下降的时候,应该是沿着梯度的反方向进行权重的更新,可以有效的找到全局的最优解。这个的更新过程可以描述为 [表示的是步长或者说是学习率(learning rate)] ?单个特征的迭代如下: ? 三、批量梯度下降在每次更新时用所有样本,在梯度下降中,对于 的更新,所有的样本都有贡献,也就是参与调整,即: ?当上式收敛时则退出迭代,何为收敛,即前后两次迭代的值不再发生变化了。一般情况下,会设置一个具体的参数,当前后两次迭代差值小于该参数时候结束迭代。 批梯度下降算法的步骤可以归纳为以下几步:
四、随机梯度下降算法:随机梯度下降算法每次迭代只是考虑让该样本点的J(θ)趋向最小,而不管其他的样本点,这样算法会很快,但是收敛的过程会比较曲折,整体效果上,大多数时候它只能接近局部最优解,而无法真正达到局部最优解。所以适合用于较大训练集的case。
随机梯度下降法突出的是随机,其本质最主要的是依赖大数定理和minibatch数据随机性对于真实梯度的经验性估计。 更准确的说是切比雪夫不等式的衍生:切比雪夫不等式显示了随机变量的“几乎所有”值都会“接近”平均。切比雪夫不等式,对任何分布形状的数据都适用: 这里就是利用随机变量去估计实际分布下的梯度,minibatch越大,经验性梯度越接近真实梯度。 随机梯度下降(SGD)算法的收敛性分析(入门版-1) - 知乎 五、mini-batch梯度下降:在每次更新时用b个样本,其实批量的梯度下降就是一种折中的方法,他用了一些小样本来近似全部的,其本质就是我1个指不定不太准,那我用个30个50个样本那比随机的要准不少了吧,而且批量的话还是非常可以反映样本的一个分布情况的。在深度学习中,这种方法用的是最多的,因为这个方法收敛也不会很慢,收敛的局部最优也是更多的可以接受! (i+=10 应为i+=b) 下面是loss的梯度图,三条线是三种梯度下降方法每下降一次的路线,蓝色是Batch Gradient Descent,紫色是Stochastic Gradient Descent,绿色是Mini-batch Gradient Descent。 进阶理解: 下面总结一下mini-batch的优点: 下面是mini-batch的伪代码,中括号上标代表层数: ?用法总结 首先,如果训练集较小,直接使用Batch Gradient Descent梯度下降法,样本集较小就没必要使用mini-batch梯度下降法,这里的少是说小于差不多2000个样本,这样比较适合使用Batch Gradient Descent梯度下降法。 样本数目较大的话,一般的mini-batch大小为64到512,考虑到电脑内存设置和使用的方式,如果mini-batch大小是2的次方,代码会运行地快一些。64到512的mini-batch比较常见。 ?六、梯度下降优化算法对随机梯度下降法来说,可怕的不是局部最优点,而是山谷和鞍点两类地形。山谷顾名思义就是狭长的山间小道,左右两边是峭壁;鞍点的形状像是一个马鞍,一个方向上两头翘, 另一个方向上两头垂,而中心区域是一片近乎水平的平地。为什么随机梯度下降法最害怕遇上这两类地形呢?在山谷中,准确的梯度方向是沿山道向下,稍有偏离就会撞向山壁,而粗糙的梯度估计使得它在两山壁间来回反弹震荡,不能沿山道方向迅速下降,导致收敛不稳定和收敛速度慢。在鞍点处,随机梯度下降法会走入一片平坦之地(此时离最低点还很远,故也称plateau)。想象一下蒙着双眼只凭借脚底感觉坡度,如果坡度很明显,那么基本能估计出下山的大致方向;如果坡度不明显,则很可能走错方向。同样,在梯度近乎为零的区域,随机梯度下降法无法准确察觉出梯度的微小变化,结果就停滞下来。 6.1 动量(Momentum)方法 Gradient descent with Momentum
? 具体来说,前进步伐,由两部分组成。一是学习速率 η乘以当前估计的梯度;二是带衰减的前一次步伐,这里,惯性就体现在对前一次步伐信息的重利用上。当前梯度就好比当前时刻受力产生的加速度,前一次步伐好比前一-时刻的速度,当前步伐好比当前时刻的速度。为了计算当前时刻的速度,应当考虑前一时刻速度和当前加速度共同作用 的结果,因此 直接依赖于?和,而不仅仅是。另外,衰减系数扮演了阻力的作用。 因为mini-batch相比标准的梯度下降来说,更新参数更快,所以收敛过程会有浮动(loss下降曲线),使用动量梯度下降法可以减小该浮动,还能加速训练。 看下mini-batch GD with Momentum的公式: 越大,收敛过程越平滑,一般取值为0.8~0.999,0.9会是一个不错的选择。 ?基本的mini-batch SGD优化算法在深度学习取得很多不错的成绩。然而也存在一些问题需解决: 1. 选择恰当的初始学习率很困难。 2. 学习率调整策略受限于预先指定的调整规则。 3. 相同的学习率被应用于各个参数。 4. 高度非凸的误差函数的优化过程,如何避免陷入大量的局部次优解或鞍点。 6.2 自适应优化AdaGrad针对简单的SGD及Momentum存在的问题,2011年John Duchi等发布了AdaGrad优化算法(Adaptive Gradient,自适应梯度),它能够对每个不同的参数调整不同的学习率,对频繁变化的参数以更小的步长进行更新,而稀疏的参数以更大的步长进行更新。 公式: 表示第t时间步的梯度(向量,包含各个参数对应的偏导数, 表示第i个参数t时刻偏导数) 表示第t时间步的梯度平方(向量,由 各元素自己进行平方运算所得,即Element-wise) 与SGD的核心区别在于计算更新步长时,增加了分母:梯度平方累积和的平方根。此项能够累积各个参数 的历史梯度平方,采用“历史梯度平方和”来衡量不同参数的梯度的稀疏性,频繁更新的梯度,则累积的分母项逐渐偏大,那么更新的步长(stepsize)相对就会变小,而稀疏的梯度,则导致累积的分母项中对应值比较小,那么更新的步长则相对比较大。 分母中求和的形式实现了退火过程,这是很多优化技术中常见的策略,意味着随着时间的推移,学习速率?越来越小。从而保证了算法的最终收敛 ?AdaGrad能够自动为不同参数适应不同的学习率(平方根的分母项相当于对学习率α进进行了自动调整,然后再乘以本次梯度),大多数的框架实现采用默认学习率α=0.01即可完成比较好的收敛。 优势:在数据分布稀疏的场景,能更好利用稀疏梯度的信息,比标准的SGD算法更有效地收敛。 缺点:主要缺陷来自分母项的对梯度平方不断累积,随之时间步地增加,分母项越来越大,最终导致学习率收缩到太小无法进行有效更新。 6.3 RMSProp root mean square propRMSProp是Geoffrey Hinton教授在教案中提到的算法,结合梯度平方的指数移动平均数来调节学习率的变化。能够在不稳定(Non-Stationary)的目标函数情况下进行很好地收敛。 Hinton教授讲述RMSProp算法的材料: http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf 计算t时间步的梯度: 计算梯度平方的指数移动平均数(Exponential Moving Average),γ是遗忘因子(或称为指数衰减率),依据经验,默认设置为0.9。
梯度更新时候,与AdaGrad类似,只是更新的梯度平方的期望(指数移动均值),其中ε=10^-8,避免除数为0。默认学习率α=0.001。 优势:能够克服AdaGrad梯度急剧减小的问题,在很多应用中都展示出优秀的学习率自适应能力。尤其在不稳定(Non-Stationary)的目标函数下,比基本的SGD、Momentum、AdaGrad表现更良好。 RMSprop的算法,全称是root mean square prop算法,它也可以加速收敛,我们来看看它是如何运作的。 ? 是一个很小的数,使后两个式子无论如何都不会除以一个接近于零的数,一般 ?原理:参数更新时 的作用是使梯度大的参数不要更新地太猛。因为梯度dW 越大, 就越大,而 就越小,参数更新的幅度就越小。 为何不把Momentum和RMSprop结合在一起用呢?那就有了Adam。 6.4 Adam方法Adaptive Momentum EstimationAdam方法将惯性保持和环境感知这两个优点集于一身。 一方面,Adam记录梯度的一阶矩(first moment),即过往梯度与当前梯度的平均,这体现了惯性保持;另一方面,Adam还记录梯度的二阶矩( sccond moment),即过往梯度平方与当前梯度平方的平均,这类似AdaGrad方法,体现了环境感知能力,为不同参数产生自适应的学习速率。一阶矩和二阶矩采用类似于滑动窗口内求平均的思想进行融合,即当前梯度和近一段时间内梯度的平均值,时间久远的梯度对当前平均值的贡献呈指数衰减。具体来说,一阶矩和二阶矩采用指数衰退平均( exponential decay average)技术,计算公式为 ? ? 其中 β1 ,β2为衰减系数,?是一阶矩,??是二阶矩。 它们的物理意义是,当 ?大且?大时,梯度大且稳定,这表明遇到一个明显的大坡,前进方向明确;当?趋于零且?大时,梯度不稳定,表明可能遇到一个峡谷,容易引起反弹震荡;当 ?大且?趋于零时,这种情况不可能出现;当 ?趋于零且?趋于零时,梯度趋于零,可能到达局部最低点,也可能走到一片坡度极缓的平地,此时要避免陷入平原( plateau)。另外,Adam方法还考虑了? 在零初始值情况下的偏置矫正。具体来说,Adam的更新公式为 ?? ?? ? 其中 β1 = 0.9 , β2 = 0.999 主要包含以下几个显著的优点:
综合Adam在很多情况下算作默认工作性能比较优秀的优化器。 6.4.1 Adam实现原理算法伪代码: ? 6.4.2 Adam更新规则计算t时间步的梯度: ? 首先,计算梯度的指数移动平均数,m0 初始化为0。 类似于Momentum算法,综合考虑之前时间步的梯度动量。 β1 系数为指数衰减率,控制权重分配(动量与当前梯度),通常取接近于1的值。 默认为0.9 ? 下图简单展示出时间步1~20时,各个时间步的梯度随着时间的累积占比情况。 ? 其次,计算梯度平方的指数移动平均数,v0初始化为0。 β2 系数为指数衰减率,控制之前的梯度平方的影响情况。 类似于RMSProp算法,对梯度平方进行加权均值。 默认为0.999 ? 第三,由于m0初始化为0,会导致mt偏向于0,尤其在训练初期阶段。 所以,此处需要对梯度均值mt进行偏差纠正,降低偏差对训练初期的影响。 ? 第四,与m0 类似,因为v0初始化为0导致训练初始阶段vt 偏向0,对其进行纠正。 ? 第五,更新参数,初始的学习率α乘以梯度均值 与梯度方差 的平方根之比。 其中默认学习率α=0.001 ε=10^-8,避免除数变为0。 由表达式可以看出,对更新的步长计算,能够从梯度均值及梯度平方两个角度进行自适应地调节,而不是直接由当前梯度决定。 ? 6.4.3 Adam代码实现算法思路很清晰,实现比较直观:
6.4.4 Adam可视化下面以Beale function为例,简单演示Adam优化器的优化路径。 https://en.wikipedia.org/wiki/Test_functions_for_optimization? ? 6.4.5 Adam缺陷及改进虽然Adam算法目前成为主流的优化算法,不过在很多领域里(如计算机视觉的对象识别、NLP中的机器翻译)的最佳成果仍然是使用带动量(Momentum)的SGD来获取到的。Wilson 等人的论文结果显示,在对象识别、字符级别建模、语法成分分析等方面,自适应学习率方法(包括AdaGrad、AdaDelta、RMSProp、Adam等)通常比Momentum算法效果更差。 针对Adam等自适应学习率方法的问题,主要两个方面的改进: 1、解耦权重衰减 ? 在每次更新梯度时,同时对其进行衰减(衰减系数w略小于1),避免产生过大的参数。 在Adam优化过程中,增加参数权重衰减项。解耦学习率和权重衰减两个超参数,能单独调试优化两个参数。 ? 2、修正指数移动均值 最近的几篇论文显示较低的β_2(如0.99或0.9)能够获得比默认值0.999更佳的结果,暗示出指数移动均值本身可能也包含了缺陷。例如在训练过程中,某个mini-batch出现比较大信息量的梯度信息,但由于这类mini-batch出现频次很少,而指数移动均值会减弱他们的作用(因为当前梯度权重 及当前梯度的平方的权重 ,权重都比较小),导致在这种场景下收敛比较差。 ? 论文作者提出Adam的变形算法AMSGrad。 AMSGrad 使用最大的 来更新梯度,而不像Adam算法中采用历史 的指数移动均值来实现。作者在小批量数据集及CIFAR-10上观察到比Adam更佳的效果。 6.5、NAG(Nesterov accelerated gradient)????? 回顾动量的方法,我们发现参数更新是基于两部分组成,一部分为当前位置的梯度,另一部分为前面累计下来的梯度值,参数更新方向就是将两者矢量相加的方向,但是我们会发现一个问题,当刚好下降到山谷附近时,如果这个时候继续以这样的方式更新参数,我们会有一个较大的幅度越过山谷,即:模型遇到山谷不会自动减弱更新的幅度。NAG针对上述问题对动量方法进行了改进,其表达式如下: 其中,表示t时刻积攒的加速度;α表示动力的大小;表示学习率;表示t时刻的模型参数,表示代价函数关于的梯度。
?它是利用当前位置处先前的梯度值先做一个参数更新,然后在更新后的位置再求梯度,将此部分梯度然后跟之前累积下来的梯度值矢量相加,简单的说就是先根据之前累积的梯度方向模拟下一步参数更新后的值,然后将模拟后的位置处梯度替换动量方法中的当前位置梯度。为什么解决了之前说的那个问题呢?因为现在有一个预测后一步位置梯度的步骤,所以当在山谷附近时,预测到会跨过山谷时,该项梯度就会对之前梯度有个修正,相当于阻止了其跨度太大。下面这张图对其有个形象描述,其中蓝色线表示动量方法,蓝色短线表示当前位置梯度更新,蓝色长线表示之前累积的梯度;第一个红色线表示用NAG算法预测下一步位置的梯度更新,第一条棕色线表示先前累积的梯度,其矢量相加结果(绿色线)就是参数更新的方向。 ? 6.6、NadamAdam将RMSprop和动量结合起来,我们也可以看到NAG其实比动量表现更好。 ?也就是现在不再像NAG提前预测后面位置,而是直接在当前位置对当前梯度方向做两次更新,同样运用到Adam中需要对m做一个修正: ? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 6:36:20- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |