💻
QMMMS的笔记
博客
  • QMMMS的笔记
  • agent
    • MCP的背景、原理和开发
    • Agent 历史与背景
    • Agentic Workflows
    • 环境检查与基础工具
    • Tool Call
    • 工具与运行时的值
    • temp
    • 处理 Tool Call error
    • trick
  • algorithm
    • 线性结构
    • 二叉树
    • 图
    • 查找
    • 排序
    • 动态规划
    • 优化方法
    • 数学
    • 迁移至Java
  • computer_composition
    • 系统总线
    • 存储器
    • 输入输出系统
    • 计算机的运算方法
    • 指令系统
    • 补充
  • computer_network
    • 引入
    • 应用层
    • 传输层
    • 网络层(数据平面)
    • 网络层(控制平面)
    • 链路层
    • 常见问答
    • 实验
  • database
    • SQL实战
    • 关系代数
    • 数据库设计
    • 规范化
    • 数据库基本概念
    • 查询原理
    • 数据库恢复技术
    • 并发控制
  • dev_tools
    • Git
    • Nginx
    • Spring
    • LangChain
    • PyTorch Cheat Sheet
    • MyBatis
    • MySQL Cheat Sheet
    • MySQL 补充
    • Redis
    • Docker
    • RocketMQ
    • Chrome
  • linux
    • Linux基础命令与使用
    • 文件与权限
    • 文件与目录操作
    • 权限属性高级
    • 命令与文件的查找
    • 文件压缩和打包
    • vim编辑器
    • shell变量
    • 命令补充
    • 数据流重定向
    • 管道命令
    • shell脚本
    • 用户管理
    • 用户间交流
    • 计划任务
    • 进程管理
    • 软件管理
    • 认识系统服务
    • 运维常用命令
    • 常用命令
  • llm
    • 大规模语言模型概述
    • 分布式训练概述
    • 有监督微调概述
    • 强化学习与LLM
    • LLM评估概述
    • 大模型应用
    • 理解大模型
    • 量化
    • 预训练
    • 上下文学习
  • machine_learning
    • 引入
    • 大致正确学习
    • 一致收敛
    • 偏差还是过拟合?
    • 可学习的充要条件
    • 非均匀可学习性
    • 计算复杂性
  • mathematics
    • 概率与统计基础
    • 线性代数基础
  • operating_system
    • 操作系统基本概念
    • 进程和线程
    • 同步,互斥与死锁
    • 内存管理
    • 文件系统
    • I/O系统
    • 保护与安全
    • 《现代操作系统》
  • statistical_learning
    • 统计学习引入
    • 线性回归
    • 分类
    • 重抽样方法
    • 线性模型选择与正则化
    • 非线性模型
    • 基于树的方法
    • 支持向量机
    • 无指导学习
    • 马尔科夫链和蒙托卡罗方法简明理解
    • R语言速查
  • deep_learning
    • basic_concepts
      • 逻辑回归与损失函数
      • 神经网络
      • 正则化、预处理、权重初始化
      • 优化算法
      • 机器学习策略
      • 复习:从计算机视觉的角度
      • 卷积神经网络
      • 深度卷积网络示例
      • 计算机视觉任务
      • 循环神经网络
      • 自然语言处理任务
      • 注意力
      • Transformers 家族
      • 显卡扫盲
      • 强化学习概述
    • semi-supervise
      • 半监督学习简介
      • Consistency Regularization
      • Proxy-label Methods
      • Holistic Methods
      • Generative Models
      • Graph-Based SSL
      • Self-Supervision for SSL
      • Other SSL methods
  • programming
    • cpp
      • STL
      • C++基础
      • 内存管理
      • 面向对象
    • java
      • 环境和介绍
      • 注释
      • String
      • 面向对象思想
      • Object
      • 包
      • 访问权限修饰符
      • 初始化块
      • 接口
      • 内部类
      • 注解
      • 枚举
      • 集合框架
      • List
      • Map
      • 泛型
      • 迭代
      • IO与流
      • 序列化
      • 异常
      • Lambda
      • Stream流
      • Socket
      • 缓冲
      • 命名规范
      • 拆箱装箱
      • 值传递
      • 深拷贝
      • 反射
      • JVM
      • 并发编程基础
    • python
      • 并发编程
      • 环境管理
  • software_engineering
    • basic_concepts
      • 系统分析与设计概述
      • 规划
      • 需求分析与原型设计
      • 项目管理
      • 建模
      • 数据库设计
      • 架构
      • 配置管理
      • 测试管理
      • 安全
      • 编码原则
      • 微服务
      • 补充内容
    • software_testing
      • CMMI基础
      • PPQA与SQA
      • 软件测试基础
      • 黑盒测试
      • 白盒测试
      • 集成测试
      • 系统测试
      • 测开面试补充
由 GitBook 提供支持
在本页
  • SGD随机梯度下降
  • Mini-batch 梯度下降
  • 思想
  • 介绍
  • 处理流程
  • 注意
  • AdaGrad
  • 动量梯度下降法
  • 思想
  • 指数加权平均数
  • 处理流程
  • RMSprop算法
  • Adam算法
  • 动画总结
  • 学习率衰减
  • 局部最优的问题
在GitHub上编辑
  1. deep_learning
  2. basic_concepts

优化算法

SGD随机梯度下降

梯度下降法中,有3中不同的策略。分别是:

  • (full) batch gradient descent = 批梯度下降,是指所有数据一次性全部喂给模型,然后用梯度下降法更新参数。这种策略的问题就是一次迭代的时间太长了,难得等。

  • mini-batch gradient descent = 小批梯度下降,是指把训练数据分成很多了mini-batch(也就是很多个数据的集合),每次喂一个mini-batch给模型,然后用梯度下降法来更新参数。这种方法是BGD和SGD这两个方法的折中。这里面也有随机。

  • stochastic gradient descent = 随机梯度下降,每次随机选择一个数据,喂给模型,然后更新参数。这种策略的问题是每次数据太少了,模型学不到什么东西。 平时我们说的随机梯度下降,就是SGD,随机是指随机选择一个数据喂给模型。

Mini-batch 梯度下降

思想

之前学过,向量化能够有效地对所有mmm个样本进行计算,允许处理整个训练集。具体来说,XXX的维数是(nx,m)(n_{x},m)(nx​,m),YYY的维数是(1,m)(1,m)(1,m),向量化能够相对较快地处理所有mmm个样本。

但是,如果mmm很大的话,处理速度仍然缓慢。比如mmm是500万或5000万或者更大的一个数。

可以把训练集分割为小一点的子集训练,这些子集被取名为mini-batch,假设每一个子集中只有1000个样本,那么把其中的x(1)x^{(1)}x(1)到x(1000)x^{(1000)}x(1000)取出来,将其称为第一个子训练集(也叫做mini-batch),称为X{1}X^{\{1\}}X{1},然后再取出接下来的1000个样本,从x(1001)x^{(1001)}x(1001)到x(2000)x^{(2000)}x(2000),称为X{2}X^{\{2\}}X{2},然后再取1000个样本,以此类推。

如果训练样本一共有500万个,每个mini-batch都有1000个样本,那么共有5000个mini-batch,最后得到是X{5000}X^{\left\{ 5000 \right\}}X{5000},维数都是(nx,1000)(n_{x},1000)(nx​,1000)。对YYY也要进行相同拆分处理,一直到Y{5000}Y^{\{ 5000\}}Y{5000},维数都是(1,1000)(1,1000)(1,1000)。

复习一下:

  • 上角小括号(i)(i)(i)表示训练集里的值,x(i)x^{(i)}x(i)是第iii个训练样本。

  • 上角中括号[l][l][l]来表示神经网络的层数,z[l]z^{\lbrack l\rbrack}z[l]表示神经网络中第lll层的zzz值。

  • 现在引入了大括号{t}\{t\}{t}来代表不同的mini-batch,有X{t}X^{\{ t\}}X{t}和Y{t}Y^{\{ t\}}Y{t}。

介绍

batch梯度下降法指的是之前讲过的(随机)梯度下降法算法(SGD),就是同时处理整个训练集。

相比之下,mini-batch梯度下降法,指的是每次同时处理的单个的mini-batch X{t}X^{\{t\}}X{t}和Y{t}Y^{\{ t\}}Y{t},而不是同时处理全部的XXX和YYY训练集。

处理流程

前向传播,具体看公式:

Z[1]=W[1]X{t}+b[1]Z^{\lbrack 1\rbrack} = W^{\lbrack 1\rbrack}X^{\{ t\}} + b^{\lbrack1\rbrack}Z[1]=W[1]X{t}+b[1]
A[1]=g[1](Z[1])A^{[1]} =g^{[1]}(Z^{[1]})A[1]=g[1](Z[1])

每层都以此类推,直到:

A[L]=g[L](Z[L])A^{\lbrack L\rbrack} = g^{\left\lbrack L \right\rbrack}(Z^{\lbrack L\rbrack})A[L]=g[L](Z[L])

计算损失成本函数JJJ(子集规模是1000,加上正则化):

J{t}=11000∑i=1lL(y^(i),y(i))+λ2⋅1000∑l∣∣W[l]∣∣F2J^{\{t\}} = \frac{1}{1000}\sum_{i = 1}^{l}{L(\hat y^{(i)},y^{(i)})} +\frac{\lambda}{2\cdot 1000}\sum_{l}^{}{||W^{[l]}||}_{F}^{2}J{t}=10001​i=1∑l​L(y^​(i),y(i))+2⋅1000λ​l∑​∣∣W[l]∣∣F2​

执行反向传播来计算J{t}J^{\{t\}}J{t}的梯度:

W[l]:=W[l]−αdW[l]W^{[l]}:= W^{[l]} - \alpha dW^{[l]}W[l]:=W[l]−αdW[l]

至此,完成了“一代”(1 epoch)的训练。“一代”这个词意味着只是一次遍历了训练集。因为有5000个mini-batch,当全部遍历一遍训练集后,能做5000个梯度下降,在训练巨大的数据集时比较常用。

注意

使用batch梯度下降法时,每次迭代你都需要历遍整个训练集,如果成本函数JJJ是迭代次数的一个函数,它应该会随着每次迭代而减少。

使用mini-batch梯度下降法,每次迭代下你都在训练不同的样本集或者说训练不同的mini-batch,如果要作出成本函数JJJ的图,很可能会看到这样的结果,走向朝下,但有更多的噪声。

Q:mini-batch的大小应该怎么选择呢?

A:样本集较小就没必要使用mini-batch梯度下降法,这里的少是说小于2000个样本,这样比较适合使用batch梯度下降法。不然,样本数目较大的话,一般的mini-batch大小为64到512。(考虑到电脑内存设置和使用的方式,如果mini-batch大小是2的nnn次方,代码会运行地快一些)

AdaGrad

AdaGrad算法是梯度下降法的改进算法,在SDG优化算法中不能自适应学习率。AdaGrad可以。

W:=W−α∑t(dW)2dWW:= W -\frac{\alpha}{\sqrt{\sum_t (dW)^2}}dWW:=W−∑t​(dW)2​α​dW
  • 在较为平缓处,梯度小,被放在了分母上,学习速率大,有比较高的学习效率。

  • 在陡峭处,梯度大,反而学习率小,在一定程度上可以避免越过极小值点。

  • 不过,注意分母是累积形式,最终会因为分母过大而梯度下降停止

动量梯度下降法

思想

Gradient descent with Momentum,或者叫做动量梯度下降法,运行速度几乎总是快于标准的梯度下降算法。基本的想法就是计算梯度的指数加权平均数。

举个例子,如果优化成本函数形状如图(蓝线),红点代表最小值的位置。如果按照传统的梯度下降算法,下降的过程将很曲折,或者说很慢。

注意到真正有用的部分是水平方向的下降,垂直方向的下降是不必要的,我们可以平均每次的偏移量,这样垂直方向的平均梯度就为0,只从水平方向梯度下降。如图红线。

此外,由于动量的存在,我们希望它在经过局部最小值点和鞍点时仍有“速度”,因此能越过这些区域。

指数加权平均数

对于一系列数据 θ1,θ2,θ3…θn\theta_1,\theta_2,\theta_3 \dots \theta_nθ1​,θ2​,θ3​…θn​,计算指数加权平均数 vtv_{t}vt​ 的递推公式为:

vt=βvt−1+(1−β)θtv_{t} = \beta v_{t - 1} + (1 - \beta)\theta_{t}vt​=βvt−1​+(1−β)θt​

其中 β\betaβ 是一个常数,最常用的值是0.9。β\betaβ 越大,曲线更平坦,原因在于你多平均了一些值。缺点是曲线进一步右移,因为现在平均的温度值更多,要平均更多的值,适应地更缓慢一些,所以会出现一定延迟。

举个例子,对于下面这张图,蓝点代表数据,红线代表的指数加权平均数选用的 β\betaβ 较小;绿线代表的指数加权平均数选用的 β\betaβ 较大。

偏差修正可以让平均数运算更加准确。

因为当 v0v_{0}v0​ 初始化为 0 时,最初计算的指数加权平均数会偏小,在估测初期,可以使用公式:

vt=βvt−1+(1−β)θt1−βtv_{t} = \frac{\beta v_{t - 1} + (1 - \beta)\theta_{t}}{1- \beta^{t}}vt​=1−βtβvt−1​+(1−β)θt​​

通常,大家不在乎执行偏差修正,因为大部分人宁愿熬过初始时期,拿到具有偏差的估测,然后继续计算下去。如果你关心初始时期的偏差,在刚开始计算指数加权移动平均数的时候,偏差修正能帮助你在早期获取更好的估测。

处理流程

简单来说,就是使用梯度的平均值来代替梯度,具体公式为:

vdW=βvdW+(1−β)dWv_{{dW}}= \beta v_{{dW}} + \left( 1 - \beta \right)dWvdW​=βvdW​+(1−β)dW
W:=W−avdWW:= W -av_{{dW}}W:=W−avdW​

RMSprop算法


使用梯度的平均值来代替梯度(类似于给grad_squared做动量),具体公式为:

SdW=βSdW+(1−β)dW2S_{dW}= {\beta} S_{dW} + (1 -{\beta}) {dW}^{2}SdW​=βSdW​+(1−β)dW2
W:=W−αdWSdW+εW:= W -\alpha \frac{dW}{\sqrt{S_{dW}}+\varepsilon}W:=W−αSdW​​+εdW​

其中,ε\varepsilonε 的加入只是为了避免分母过小,10−810^{-8}10−8是个不错的选择。 β\betaβ 依旧是一个常数,这里最常用的值是0.999。

Adam算法


Adam算法(Adam optimization algorithm),基本上就是将Momentum和RMSprop结合在一起,思想也类似,使用梯度的平均值来代替梯度,具体流程如下 :

首先根据上面的公式计算出 vdWv_{{dW}}vdW​, SdWS_{dW}SdW​

计算偏差修正的值,因为Momentum和RMSprop都会使用β\betaβ,所以区分β1{\beta}_1β1​和β2{\beta}_2β2​

vdWcorrected=vdW1−β1t,SdWcorrected=SdW1−β2tv_{dW}^{\text{corrected}}= \frac{v_{dW}}{1 - \beta_{1}^{t}},S_{dW}^{\text{corrected}} =\frac{S_{dW}}{1 - \beta_{2}^{t}}vdWcorrected​=1−β1t​vdW​​,SdWcorrected​=1−β2t​SdW​​

最后更新权重

W:=W−avdWcorrectedSdWcorrected+εW:= W - \frac{a v_{dW}^{\text{corrected}}}{\sqrt{S_{dW}^{\text{corrected}}} +\varepsilon}W:=W−SdWcorrected​​+εavdWcorrected​​
  • 其中,Momentum使用的β1{\beta}_1β1​常用的缺省值为0.9

  • RMSprop使用的β2{\beta}_2β2​常用的缺省值为0.999

  • ε\varepsilonε 常用的缺省值为10−810^{-8}10−8

  • 这三个超参数没那么重要,一般情况下,并不需要特别调试它

动画总结

  • Momentum(动量法):模拟物理动量的概念,积累之前的动量来替代真正的梯度

  • Adagrad(Adaptive Gradient):每个参数反比于历史梯度平方总和的平方根

  • RMSprop(Root Mean Squared propagation):AdaGrad的升级。通过平均梯度的平方来调整学习率,从而缓解训练过程中的震荡。

  • Adam(Adaptive Moment Estimation):Momentum+ RMSProp + Bias Correction(偏差修正)是目前最流行和常用的优化算法之一。

更多动画例子可以看:https://juntang-zhuang.github.io/adabelief/

学习率衰减

加快学习算法的一个办法就是随时间慢慢减少学习率,称为学习率衰减。在学习初期,能承受较大的步伐,但当开始收敛的时候,小一些的学习率能让步伐小一些。可以更稳定地靠近优化成本函数的最小值。

一些比较常见的控制学习率衰减的函数包括:

α=11+decayrate∗epoch-numα0\alpha= \frac{1}{1 + decayrate * \text{epoch}\text{-num}}{\alpha}_{0}α=1+decayrate∗epoch-num1​α0​
α=0.95epoch-numα0\alpha ={0.95}^{\text{epoch-num}} {\alpha}_{0}α=0.95epoch-numα0​
α=kepoch-numα0\alpha =\frac{k}{\sqrt{\text{epoch-num}}}{\alpha}_{0}α=epoch-num​k​α0​
  • decay-rate为衰减率,是另一个需要调整的超参数

  • epoch-num为代数

  • α0\alpha_{0}α0​ 为初始学习率

  • kkk 为一个常数

也可以尝试在训练时手动衰减 α\alphaα

局部最优的问题

在深度学习研究早期,人们总是担心优化算法会困在极差的局部最优。梯度下降法或者某个算法可能困在一个局部最优中,而不会抵达全局最优。如下图:

事实上,对于一个神经网络,成本函数是一个具有高维度空间的函数,通常梯度为零的点并不是这个图中的局部最优点,而是鞍点。因为不太容易出现每个维度都是梯度为零的情况。在这种情况下,可以在另一个维度上梯度下降。

上一页正则化、预处理、权重初始化下一页机器学习策略

最后更新于9个月前

两种梯度下降法的区别
指数加权平均数
Long Valley - Imgur
Saddle Point - Imgur
困在极差的局部最优
鞍点