【深度学习】03-神经网络 3-3 梯度下降的优化方法-动量算法Momentum

embedded/2024/9/24 11:44:44/

常规的梯度下降算法中,会遇到平缓区域,碰到鞍点,碰到局部最小值(截止当前无解),因此为了解决这个问题,我们需要优化传统的梯度下降算法

动量算法(Momentum) 是梯度下降算法的一种优化方法,旨在解决传统梯度下降容易陷入局部最小值或在鞍点附近震荡的问题。动量算法通过引入一个“动量”的概念,能够加速梯度下降的收敛,并帮助模型更快地找到全局最优解。

1. 梯度下降的基本问题

在常规的梯度下降中,模型通过计算损失函数的梯度,并根据这个梯度的方向更新参数。公式如下:

[ \theta = \theta - \eta \cdot \nabla_\theta J(\theta) ]

其中:

  • ( \theta ) 是模型的参数。

  • ( \eta ) 是学习率。

  • ( \nabla_\theta J(\theta) ) 是参数 ( \theta )  方向的梯度。

在简单的梯度下降中,如果损失函数的形状复杂,比如有很多曲率不同的区域,模型在某些方向上的更新会过快,导致在目标最小值附近震荡,或者更新速度过慢,导致收敛时间变长。

2. 动量算法(Momentum)概述

动量算法的关键思想是:不仅仅考虑当前梯度对参数更新的影响,还考虑之前梯度的影响。通过引入“动量”这一概念,算法能够“加速”向最优解的方向前进。

动量算法通过以下公式更新参数:

[ v_t = \gamma v{t-1} + \eta \nabla\theta J(\theta) ]

[ \theta = \theta - v_t ]

其中:

  • ( v_t )是第 ( t )步时的速度(或动量),表示之前梯度的累积方向。

  • ( \gamma )是动量项(通常取值为 0.9 左右),用于控制之前梯度对当前更新的影响,类似于惯性。

  • ( \eta ) 是学习率,用于控制每一步更新的幅度。

  • ( \nabla_\theta J(\theta) )是当前梯度。

3. 动量的作用

  • 平滑更新方向:通过将前几次更新方向上的“动量”引入当前更新,动量算法能够平滑梯度更新的方向,避免在陡峭区域产生剧烈的梯度更新,从而减少震荡。

  • 加速收敛:在平坦的区域或相对低曲率的地方,动量会使得更新步伐逐渐加快,加速收敛到最优解。

  • 帮助逃离局部最小值:由于动量带来的累积效果,模型可以更容易地摆脱局部最小值的困扰,帮助找到更好的全局最优解。

代码:

import torchdef momentum_optimization_example():# Step 1: 初始化一个可训练的张量 w,设置 requires_grad=True 表示 w 的梯度需要计算w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)  # 权重初始化为 1.0,类型为 float32# 定义一个简单的目标函数(损失函数): y = (w^2) / 2y = ((w ** 2) / 2.0).sum()# Step 2: 使用 SGD 优化器并带有动量(momentum=0.9)# - 学习率 lr = 0.01# - 动量系数 beta = 0.9optimizer = torch.optim.SGD([w], lr=0.01, momentum=0.9)# 梯度清零(非常重要,防止梯度累加)optimizer.zero_grad()# 计算目标函数 y 对 w 的梯度y.backward()  # 反向传播计算梯度# 使用带动量的 SGD 进行参数更新optimizer.step()  # 使用 optimizer.step() 更新参数 w# 打印更新后的梯度和 w 值print('Step 1: w 的梯度: %f, 更新后的 w 值: %f' % (w.grad.numpy(), w.detach().numpy())) # Step 3: 继续第二轮的梯度更新# 重新计算损失函数,基于更新后的 w 值y = ((w ** 2) / 2.0).sum()# 在第二轮梯度计算前需要将之前的梯度清零optimizer.zero_grad()# 计算目标函数对新 w 的梯度y.backward()# 再次更新参数 woptimizer.step()# 打印第二次更新后的梯度和 w 值print('Step 2: w 的梯度: %f, 更新后的 w 值: %f' % (w.grad.numpy(), w.detach().numpy())) # 调用函数进行动量算法优化示例
momentum_optimization_example()

代码讲解:

        1. 初始化权重 w

w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)
  1. w 是一个可训练的权重,初始化为 1.0。requires_grad=True 表示需要计算其梯度,dtype=torch.float32 指定了数据类型。

  2. 我们将优化这个 w,使其能够最小化损失函数  ( y = \frac{w^2}{2} )

  3. 2.定义损失函数 y

    • y = ((w ** 2) / 2.0).sum()

      损失函数 ( y = \frac{w^2}{2} ) 是我们要最小化的目标。在这个示例中,它是一个非常简单的二次函数。
    • 通过最小化这个损失函数,我们可以观察到参数更新过程中的动量算法

  4. 3.优化器 optimizer

    optimizer = torch.optim.SGD([w], lr=0.01, momentum=0.9)
    • 使用了随机梯度下降(SGD)作为优化器,并设置了动量项 momentum=0.9。动量可以加速梯度下降过程,尤其是在复杂或有噪声的损失函数中。

    • 学习率 lr=0.01 控制每次更新的步长,动量系数 momentum=0.9 决定了累积历史梯度的影响。

  5. 4.梯度清零

    optimizer.zero_grad()
    • 在每次计算新的梯度之前,我们需要将前一步的梯度清零。否则,PyTorch 会将梯度累加。

  6. 5. 反向传播计算梯度

    y.backward()
    • backward() 函数会根据损失函数计算出参数 w 的梯度,即 y w 的偏导数。

  7. 6. 更新参数 w

    optimizer.step()
    • 调用 optimizer.step() 后,优化器会根据计算出的梯度和动量,更新权重 w 的值。

  8. 7. 打印梯度和更新后的参数

    print('Step 1: w 的梯度: %f, 更新后的 w 值: %f' % (w.grad.numpy(), w.detach().numpy()))
    • w.grad 表示当前权重 w 的梯度值。

    • w.detach() 返回的是更新后的权重值,并且从计算图中分离出来,不会再继续跟踪梯度。

动量算法原理简要说明:

动量算法在梯度下降的过程中,通过累积过去的梯度来加速优化。具体原理如下:

  1. 动量可以理解为模拟物理系统中物体的惯性,它在梯度下降过程中累积了之前的更新方向,使得参数更新更加平滑、稳定。

  2. 公式

    • 在动量算法中,每次更新时会引入历史梯度的影响:

    • [ v_t = \beta v{t-1} + (1 - \beta) \nabla\theta J(\theta) ]

    • 其中 ( v_t ) 是当前的动量值,( \beta )是动量系数,

    • 通常接近 1(例如 0.9)。动量项 ( v_t )  可以看作是梯度的指数加权平均。

    • 接着,使用 ( v_t )来更新参数:[ \theta = \theta - v_t ]

在代码中,momentum=0.9 就是使用了动量项,帮助梯度在下降的过程中减少震荡,加速收敛。

4. 动量算法的更新过程详解

每次迭代时,动量算法通过计算两个关键公式:

  1. 速度更新公式[ v_t = \gamma v{t-1} + \eta \nabla\theta J(\theta) ]

    • 这一步表示计算当前的动量,它是前一次动量 ( v_{t-1} )和当前梯度的加权和。这样可以保证之前的更新方向对当前更新有影响。

  2. 参数更新公式[ \theta = \theta - v_t ]

    • 这一步表示用更新后的动量 ( v_t ) 来调整参数\theta,这样可以使得模型在朝向最优解的方向上有更稳定和加速的更新。

5. 动量算法的直观理解

可以把动量算法想象成一个球沿着曲面滚动的过程。传统的梯度下降类似于每一步都按照曲面的斜率(梯度)前进,而动量算法则模拟了一个带有惯性的球滚动的行为:

  • 惯性作用:球滚动时不仅受到当前坡度的影响,还会受到前面滚动过程中积累的速度(动量)的影响,这样就能够滚得更远、更快。

  • 减少震荡:在复杂的损失函数表面,动量算法可以避免在凹凸不平的表面上来回振荡,而是保持一个平滑的轨迹。

6. 动量算法的优势

  • 减少震荡:动量算法能够减少梯度下降过程中在局部最优或鞍点附近的震荡。

  • 加速收敛:通过累积梯度方向上的动量,动量算法能够加快模型的收敛速度,特别是在长梯度路径上。

  • 对局部最优点的鲁棒性:动量算法能够有效避免模型陷入局部最优点,增加找到全局最优解的机会。

7. 动量算法的常见变种

  • Nesterov 动量(Nesterov Accelerated Gradient, NAG):Nesterov 动量是在标准动量算法的基础上做了改进,NAG 会先看一步未来的梯度,然后再进行更新,以达到更好的预见性。它的更新公式如下:[ v_t = \gamma v{t-1} + \eta \nabla\theta J(\theta - \gamma v_{t-1}) ]这种方法往往比标准动量更快收敛,尤其是在复杂的损失函数中。

8. 动量算法的应用

动量算法被广泛应用于神经网络训练中,尤其是在深度学习任务中,它可以有效提升训练速度并且提高模型的性能。它可以和其他优化方法(如自适应优化算法 Adam)结合使用,进一步优化模型的学习效果。

总结

  • 动量算法 是一种改进的梯度下降方法,通过引入“动量”来减少震荡、加速收敛,并避免陷入局部最优解。

  • 通过结合当前和过去的梯度更新,动量算法能够有效改善传统梯度下降的缺陷,尤其在神经网络训练中表现优异。

  • Nesterov 动量 是动量算法的一种改进变种,能够进一步加速收敛,尤其在较为复杂的损失函数表面。


http://www.ppmy.cn/embedded/116076.html

相关文章

谈一谈 DDD

一、前言 最近 10 年的互联网发展,从电子商务到移动互联,再到“互联网+”与传统行业的互联网转型,是一个非常痛苦的转型过程。在这个过程中,一方面会给我们带来诸多的挑战,另一方面又会给我们带来无尽的机会,它会带来更多的新兴市场、新兴产业与全新业务,给我们带来全新…

Jetpack——Room

概述 Room是谷歌公司推出的数据库处理框架,该框架同样基于SQLite,但它通过注解技术极大简化了数据库操作,减少了原来相当一部分编码工作量。在使用Room之前,要先修改模块的build.gradle文件,往dependencies节点添加下…

nginx使用stream转发流量

stream { upstream backend { # 后端服务器列表 server 192.168.1.10:3306; # 第一个后端服务器 server 192.168.1.11:3306; # 第二个后端服务器 # 可以添加更多服务器 } server { listen 3306; # 监听的端口 proxy_p…

速盾:高防cdn除了快还有什么好处?

高防CDN(Content Delivery Network)是现今互联网基础架构中的一项重要技术,它不仅能够提供快速的内容分发,还具备许多其他的好处。以下将详细介绍高防CDN的优势和好处。 首先,高防CDN能够提供快速的内容分发。由于CDN…

高刷显示器哪个好?540Hz才有资格称高刷

高刷显示器哪个好?说实话,540Hz这些才能成为高刷显示器,什么200,240的,都不够高,什么是从容,有我不用才叫从容。下面我们一起来看看540Hz的高刷显示器都有哪些吧! 1.高刷显示器哪个好 - 蚂蚁电…

初始docker以及docker的基本使用!!!

文章目录 虚拟化技术Docker/podman 命令通用命令查看docker 当前版本管理docker运行 镜像操作[image]列出本地所有镜像拉取镜像删除镜像把docker中的镜像打包成文件把镜像文件加载到docker中上传镜像 容器操作[container]创建容器docker run的参数选项列出所有容器启动容器停止…

AI 基础设施:构建AI时代全栈云计算体系

生成式AI 新时代下催生新的基础设施需求 随着企业在数字化转型之路上越走越远,期间一场新的技术革命正在发生,近几年涌现的生成式AI技术正在迅速改变科技、商业和整个社会的格局。这种强大的技术能够从数据中学习并生成预测性输出,生成式 AI …

Linux通过yum安装Docker

目录 一、安装环境 1.1. 旧的docker包卸载 1.2. 安装常规环境包 1.3. 设置存储库 二、安装Docker社区版 三、解决拉取镜像失败 3.1. 创建文件目录/etc/docker 3.2. 写入镜像配置 https://docs.docker.com/engine/install/centos/ 检测操作系统版本,我操作的…