Geeks_Z の Blog Geeks_Z の Blog
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)

Geeks_Z

AI小学生
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)
  • Python

  • MLTutorials

    • 机器学习基础

    • 模型与算法

    • 模型优化

      • 局部极小值与鞍点
      • 批量和动量
      • 学习率
        • 调整学习速率
        • AdaGrad
          • Adagrad举例
          • Adagrad 存在的矛盾?
          • 多参数下结论不一定成立
          • Adagrad 进一步的解释
        • 随机梯度下降法
        • RMSProp
        • Adam
        • 学习率调整
      • 梯度下降
      • 反向传播
      • 优化算法
      • 各种Optimizer梯度下降优化算法回顾和总结
      • AI算法工程师必备的深度学习最优化上
      • PyTorch优化神经网络训练的17种方法
      • AdamW与Adam的比较可能AdamW依然是最好的优化器
      • 机器学习调参自动优化方法
      • Dropout
  • 卷积神经网络

  • 循环神经网络

  • Transformer

  • VisionTransformer

  • 扩散模型

  • 计算机视觉

  • PTM

  • MoE

  • LoRAMoE

  • LongTailed

  • 多模态

  • 知识蒸馏

  • PEFT

  • 对比学习

  • 小样本学习

  • 迁移学习

  • 零样本学习

  • 集成学习

  • Mamba

  • PyTorch

  • CL

  • CIL

  • 小样本类增量学习FSCIL

  • UCIL

  • 多模态增量学习MMCL

  • LTCIL

  • DIL

  • 论文阅读与写作

  • 分布外检测

  • GPU

  • 深度学习调参指南

  • AINotes
  • MLTutorials
  • 模型优化
Geeks_Z
2024-10-10
目录

学习率

临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍。图 3.18 中的横坐标代表参数更新的次数,竖坐标表示损失。一般在训练一个网络的时候,损失原来很大,随着参数不断的更新,损失会越来越小,最后就卡住了,损失不再下降。当我们走到临界点的时候,意味着梯度非常小,但损失不再下降的时候,梯度并没有真的变得很小,图 3.19 给出了示例。图 3.19 中横轴是迭代次数,竖轴是梯度的范数(norm),即梯度这个向量的长度。随着迭代次数增多,虽然损失不再下降,但是梯度的范数并没有真的变得很小。

图 3.20 是误差表面,梯度在山谷的两个谷壁间,不断地来回“震荡”,这个时候损失不会再下降,它不是真的卡到了临界点,卡到了鞍点或局部最小值。但它的梯度仍然很大,只是损失不一定再减小了。所以训练一个网络,训练到后来发现损失不再下降的时候,有时候不是卡在局部最小值或鞍点,只是单纯的损失无法再下降。

我们现在训练一个网络,训练到现在参数在临界点附近,再根据特征值的正负号判断该临界点是鞍点还是局部最小值。实际上在训练的时候,要走到鞍点或局部最小值,是一件困难的事情。一般的梯度下降,其实是做不到的。用一般的梯度下降训练,往往会在梯度还很大的时候,损失就已经降了下去,这个是需要特别方法训练的。要走到一个临界点其实是比较困难的,多数时候训练在还没有走到临界点的时候就已经停止了。

调整学习速率

举例:

上图左边黑色为损失函数的曲线,假设从左边最高点开始,如果学习率调整的刚刚好,比如红色的线,就能顺利找到最低点。如果学习率调整的太小,比如蓝色的线,就会走的太慢,虽然这种情况给足够多的时间也可以找到最低点,实际情况可能会等不及出结果。如果 学习率调整的有点大,比如绿色的线,就会在上面震荡,走不下去,永远无法到达最低点。还有可能非常大,比如黄色的线,直接就飞出去了,更新参数的时候只会发现损失函数越更新越大。

虽然这样的可视化可以很直观观察,但可视化也只是能在参数是一维或者二维的时候进行,更高维的情况已经无法可视化了。

解决方法就是上图右边的方案,将参数改变对损失函数的影响进行可视化。比如学习率太小(蓝色的线),损失函数下降的非常慢;学习率太大(绿色的线),损失函数下降很快,但马上就卡住不下降了;学习率特别大(黄色的线),损失函数就飞出去了;红色的就是差不多刚好,可以得到一个好的结果。

AdaGrad

AdaGrad(Adaptive Gradient)是典型的自适应学习率方法,其能够根据梯度大小自动调整学习率。AdaGrad可以做到梯度比较大的时候,学习率就减小,梯度比较小的时候,学习率就放大。

梯度下降更新某个参数 θti 的过程为

θt+1i←θti−ηgti(3.14)

θti 在第 t 个迭代的值减掉在第 t 迭代参数 i 出来的梯度

gti=∂L∂θi|θ=θt(3.15)

gti 代表在第 t 迭代,即 θ=θt 时,损失 L 关于参数 θi 的偏导,学习率是固定的。

现在要有一个随着参数定制化的学习率,即把原来学习率 η 变成 ησti:

θt+1i←θti−ησtigti(3.16)

σti 的上标为 i,这代表参数 σ 与 i 相关,不同的参数的 σ 不同。σti 的下标为 t,这代表参数 σ 与迭代相关,不同的迭代也会有不同的 σ。学习率从 η 改成 ησti 的时候,学习率就变得参数相关(parameter dependent)。

参数相关的一个常见的类型是算梯度的均方根(root mean square)。参数的更新过程为

θ1i←θ0i−ησ0ig0i(3.17)

其中 θ0i 是初始化参数。而 σ0i 的计算过程为

σ0i=(g0i)2=|g0i|(3.18)

其中 g0i 是梯度。将 σ0i 的值代入更新的公式可知 g0iσ0i 的值是 +1 或 -1。第一次在更新参数,从 θ0i 更新到 θ1i 的时候,要么是加上 η,要么是减掉 η,跟梯度的大小无关,这个是第一步的情况。

第二次更新参数过程为

θ2i←θ1i−ησ1ig1i(3.19)

其中 σ1i 是过去所有计算出来的梯度的平方的平均再开根号,即均方根,如式(3.20)所示。

σ1i=12[(g0i)2+(g1i)2](3.20)

同样的操作反复继续下去,如式(3.21)所示。

θ3i←θ2i−ησ2ig2iσ2i=13[(g0i)2+(g1i)2+(g2i)2](3.21)

第 t+1 次更新参数的时候,即

θt+1i←θti−ησtigtiσti=1t+1∑j=0t(gji)2(3.22)

ησti 当作是新的学习率来更新参数。

图 3.24中有两个参数:θ1 和 θ2。θ1 坡度小,θ2 坡度大。因为 θ1 坡度小,根据式(3.22), θ1 这个参数上面算出来的梯度值都比较小,因为梯度算出来的值比较小,所以算出来的 σti 就小,σti 小学习率就大。反过来,θ2 坡度大,所以计算出的梯度都比较大,σti 就比较大,在更新的时候,步伐(参数更新的量)就比较小。因此有了 σti 这一项以后,就可以随着梯度的不同,每一个参数的梯度的不同,来自动调整学习率的大小。

Adagrad举例

下图是一个参数的更新过程

将 Adagrad 的式子进行化简:

Adagrad 存在的矛盾?

在 Adagrad 中,当梯度越大的时候,步伐应该越大,但下面分母又导致当梯度越大的时候,步伐会越小。

下图是一个直观的解释:

下面给一个正式的解释:

比如初始点在 x0,最低点为 −b2a,最佳的步伐就是 x0 到最低点之间的距离 |x0+b2a|,也可以写成 |2ax0+b2a|。而刚好 |2ax0+b| 就是方程绝对值在 x0 这一点的微分。

这样可以认为如果算出来的微分越大,则距离最低点越远。而且最好的步伐和微分的大小成正比。所以如果踏出去的步伐和微分成正比,它可能是比较好的。

结论1-1:梯度越大,就跟最低点的距离越远。

这个结论在多个参数的时候就不一定成立了。

多参数下结论不一定成立

对比不同的参数

上图左边是两个参数的损失函数,颜色代表损失函数的值。如果只考虑参数 w1,就像图中蓝色的线,得到右边上图结果;如果只考虑参数 w2,就像图中绿色的线,得到右边下图的结果。确实对于 a 和 b,结论1-1是成立的,同理 c 和 b 也成立。但是如果对比a 和 c,就不成立了,c 比 a 大,但 c 距离最低点是比较近的。

所以结论1-1是在没有考虑跨参数对比的情况下,才能成立的。所以还不完善。

之前说到的最佳距离 |2ax0+b2a|,还有个分母 2a 。对function进行二次微分刚好可以得到:

(7)∂2y∂x2=2a

所以最好的步伐应该是:

一次微分二次微分一次微分二次微分

即不止和一次微分成正比,还和二次微分成反比。最好的step应该考虑到二次微分:

Adagrad 进一步的解释

再回到之前的 Adagrad

对于 ∑i=0t(gi)2 就是希望再尽可能不增加过多运算的情况下模拟二次微分。(如果计算二次微分,在实际情况中可能会增加很多的时间消耗)

随机梯度下降法

之前的梯度下降:

而随机梯度下降法更快:

损失函数不需要处理训练集所有的数据,选取一个例子

此时不需要像之前那样对所有的数据进行处理,只需要计算某一个例子的损失函数 ,就可以赶紧 update 梯度。

对比:

img

常规梯度下降法走一步要处理到所有二十个例子,但随机算法此时已经走了二十步(每处理一个例子就更新)

RMSProp

同一个参数需要的学习率,也会随着时间而改变。在图 3.25中的误差表面中,如果考虑横轴方向,绿色箭头处坡度比较陡峭,需要较小的学习率,但是走到红色箭头处,坡度变得平坦了起来,需要较大的学习率。因此同一个参数的同个方向,学习率也是需要动态调整的,于是就有了一个新的方法 - RMSprop(Root Mean Squared propagation)。

RMSprop没有论文,Geoffrey Hinton在 Coursera上开过深度学习的课程,他在他的课程里面讲了 RMSprop,如果要引用,需要引用对应视频的链接。

RMSprop第一步跟 Adagrad的方法是相同的,即

σ0i=(g0i)2=|g0i|(3.23)

第二步更新过程为

θ2i←θ1i−ησ1ig1iσ1i=α(σ0i)2+(1−α)(g1i)2(3.24)

其中 0<α<1,其是一个可以调整的超参数。计算 θ1i 的方法跟 AdaGrad算均方根不一样,在算均方根的时候,每一个梯度都有同等的重要性,但在 RMSprop里面,可以自己调整现在的这个梯度的重要性。如果α 很小趋近于0,代表g’相较于之前算出来的梯度而言,比较重要;如果α 设很大趋近于1,代表g比较不重要,之前算出来的梯度比较重要。同样的过程就反复继续下去,如式(3.25)所示。

θt+1i←θti−ηα(σti)2+(1−α)(gti)2gtiσt+1i=α(σti)2+(1−α)(gti)2(3.25)

RMSProp 通过 α 可以决定,gti 相较于之前存在 σti 里面的 g0i,g1i,…,gt−1i 的重要性有多大。如果使用 RMSprop,就可以动态调整 σti 这一项。图3.26 中黑线是误差表面,球就从A走到B,AB段的路很平坦,gti 很小,更新参数的时候,我们会走比较大的步伐。走到 BC 段后梯度变大了,AdaGrad 反应比较慢,而 RMSprop 会把 α 设小一点,让新的、刚看到的梯度的影响比较大,很快地让 σti 的值变大,很快地让步伐变小,RMSprop 可以很快地“踩刹车”。如果走到 CD 段,CD 段是平坦的地方,可以调整α,让其比较看重最近算出来的梯度,梯度一变小,σti 的值就变小了,走的步伐就变大了。

Adam

最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estimation)。Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自适应调整学习率。PyTorch 里面已经写好了 Adam 优化器,这个优化器里面有一些超参数需要人为决定,但是往往用 PyTorch 预设的参数就足够好了。

学习率调整

如图3.22所示的简单的误差表面,我们都训练不起来,加上自适应学习率以后,使用AdaGrad方法优化的结果如图3.27所示。一开始优化的时候很顺利,在左转的时候,有AdaGrad以后,可以再继续走下去,走到非常接近终点的位置。走到BC段时,因为横轴方向的梯度很小,所以学习率会自动变大,步伐就可以变大,从而不断前进。接下来的问题走到图3.27中红圈的地方,快走到终点的时候突然“爆炸”了。σti 把过去所有的梯度拿来作平均。在AB段梯度很大,但在BC段,纵轴的方向梯度很小,因此纵轴方向累积了很小的σti,累积到一定程度以后,步伐就变很大,但有办法修正回来。因为步伐很大,其会走到梯度比较大的地方。走到梯度比较大的地方后,σti 慢慢变大,更新的步伐大小会慢慢变小,从而回到原来的路线。

通过学习率调度 (learning rate scheduling) 可以解决这个问题。之前的学习率调整方法中 η 是一个固定的值,而在学习率调度中 η 跟时间有关,如式(3.26)所示。学习率调度中最常见的策略是学习率衰减 (learning rate decay),也称为学习率退火 (learning rate annealing)。随着参数的不断更新,让 η 越来越小,如图 3.28所示。图 3.27的情况,如果加上学习率下降,可以很平顺地走到终点,如图 3.29所示。在图 3.27红圈的地方,虽然步伐很大,但 η 变得非常小,步伐乘上 η 就变小了,就可以慢慢地走到终点。

θt+1i←θti−ηtσtigti(3.26)

除了学习率下降以外,还有另外一个经典的学习率调度的方式——预热。预热的方法是让学习率先变大后变小,至于变到多大、变大的速度、变小的速度是超参数。残差网络 [8] 里面是有预热的,在残差网络里面,学习率先设置成 0.01,再设置成 0.1,并且其论文还特别说明,一开始用 0.1 反而训练不好。除了残差网络,BERT和 Transformer的训练也都使用了预热。

Q: 为什么需要预热? A: 当我们使用Adam、RMSprop或AdaGrad时,需要计算 σ。而 σ 是一个统计的结果。从 σ 可知某一个方向的陡峭程度。统计的结果需要足够多的数据才精准,一开始统计结果 σ 是不精准的。一开始学习率比较小是用来探索收集一些有关误差表面的情报,先收集有关 σ 的统计数据,等 σ 统计得比较精准以后,再让学习率慢慢爬升。如果读者想要学更多有关预热的东西可参考Adam的进阶版 - RAdam[9]。

所以我们从最原始的梯度下降,进化到这一个版本,如式(3.27)所示。

θt+1i←θti−ηtσtimti(3.27)

其中 mti 是动量。

这个版本里面有动量,其不是顺着某个时刻算出的梯度方向来更新参数,而是把过去所有算出梯度的方向做一个加权总和当作更新的方向。接下来的步伐大小为 mtiσti。最后通过 ηt 来实现学习率调度。这个是目前优化的完整的版本,这种优化器除了 Adam以外,还有各种变形。但其实各种变形是使用不同的方式来计算 mti 或 σti,或者是使用不同的学习率调度的方式。

Q: 动量 mti 考虑了过去所有的梯度,均方根 σti 考虑了过去所有的梯度,一个放在分子,一个放在分母,并且它们都考虑过去所有的梯度,不就是正好抵消了吗? A: mti 和 σti 在使用过去所有梯度的方式是不一样的,动量是直接把所有的梯度都加

上次更新: 2025/06/25, 11:25:50
批量和动量
梯度下降

← 批量和动量 梯度下降→

最近更新
01
帮助信息查看
06-08
02
常用命令
06-08
03
学习资源
06-07
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Geeks_Z | MIT License
京公网安备 11010802040735号 | 京ICP备2022029989号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式