深度学习中的优化方法(Momentum,AdaGrad,RMSProp,Adam)详解及调用

news2024/11/27 14:42:02

深度学习中常用的优化方法包括啦momentum(动量法),Adagrad(adaptive gradient自适应梯度法),RMSProp(root mean square propagation均方根传播算法),Adam(adaptive moment estimation自适应矩估计法)

指数加权平均算法

所谓指数加权平均算法是上述优化算法的基础,其作用是对历史数据和当前数据进行加权求和,具体公式如下

if t==0:

v_0 = x_0

if t > 0

v_t = \beta v_{t-1} + (1 - \beta) x_t

其中

  • v_t为时间步t的加权平均值
  • v_{t-1}为为时间步t-1的加权平均值
  • x_t为时间步t的观测值
  • \beta为平滑因子,0 < \beta < 1

可以较为明显地看出,所谓指数加权平均算法的关键就在于\beta的大小,其越大,当前时间步的值就会越偏向过去的值,换句话说,整体数值序列就会更加平滑

指数加权平均算法的可视化

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from numpy.array_api import linspace

torch.manual_seed(0)


def exponential_wma(data,beta=0.9):
    list1 = []
    for n,i in enumerate(data):
        if n ==0:
            list1.append(i)
        else:
            list1.append(beta * list1[n-1] + (1-beta) * i)
    return list1

if __name__ == '__main__':


    data = torch.randn(50)*10

    x = torch.linspace(1,50,50)

    fig = plt.figure()
    axes1 = plt.subplot(1,2,1)
    axes1.scatter(x,data)
    axes1.plot(x,data)
    axes1.set_xlabel('x')
    axes1.set_ylabel('y')
    axes1.set_title('original data')
    print(data)

    axes2 = plt.subplot(1,2,2)
    axes2.scatter(x,data,label='original_data')
    axes2.plot(x,exponential_wma(data),  label='ewma_curve')
    axes2.set_xlabel('x')
    axes2.set_ylabel('y')
    axes2.set_title('ewma')
    print(exponential_wma(data))
    axes2.legend()
    plt.subplots_adjust(wspace=0.4)
    fig.savefig('ewma.png')
    plt.show()

# tensor([-11.2584, -11.5236,  -2.5058,  -4.3388,   8.4871,   6.9201,  -3.1601,
#         -21.1522,   3.2227, -12.6333,   3.4998,   3.0813,   1.1984,  12.3766,
#          11.1678,  -2.4728, -13.5265, -16.9593,   5.6665,   7.9351,   5.9884,
#         -15.5510,  -3.4136,  18.5301,   7.5019,  -5.8550,  -1.7340,   1.8348,
#          13.8937,  15.8633,   9.4630,  -8.4368,  -6.1358,   0.3159,  10.5536,
#           1.7784,  -2.3034,  -3.9175,   5.4329,  -3.9516,   2.0553,  -4.5033,
#          15.2098,  34.1050, -15.3118, -12.3414,  18.1973,  -5.5153, -13.2533,
#           1.8855])
# [tensor(-11.2584), tensor(-11.2849), tensor(-10.4070), tensor(-9.8002), tensor(-7.9715), tensor(-6.4823), tensor(-6.1501), tensor(-7.6503), tensor(-6.5630), tensor(-7.1700), tensor(-6.1030), tensor(-5.1846), tensor(-4.5463), tensor(-2.8540), tensor(-1.4518), tensor(-1.5539), tensor(-2.7512), tensor(-4.1720), tensor(-3.1881), tensor(-2.0758), tensor(-1.2694), tensor(-2.6976), tensor(-2.7692), tensor(-0.6392), tensor(0.1749), tensor(-0.4281), tensor(-0.5587), tensor(-0.3193), tensor(1.1020), tensor(2.5781), tensor(3.2666), tensor(2.0962), tensor(1.2730), tensor(1.1773), tensor(2.1150), tensor(2.0813), tensor(1.6428), tensor(1.0868), tensor(1.5214), tensor(0.9741), tensor(1.0822), tensor(0.5237), tensor(1.9923), tensor(5.2036), tensor(3.1520), tensor(1.6027), tensor(3.2621), tensor(2.3844), tensor(0.8206), tensor(0.9271)]

这里设置的平滑因子为0.9,通常情况下使用动量法的时候平滑因子也会设置为0.9

平滑因子越大,理论上曲线就会越平滑

Momentum动量法

Momentum动量法的原理就是在梯度下降的时候使用指数加权平均法计算下降的梯度

动量更新方法如下

v_{t+1} = \beta v_t + (1 - \beta) \nabla_{\theta} J(\theta_t)

其中

  • v_{t+1}是动量项(累积的梯度),用于更新参数。
  • \beta 是动量系数(通常 0 < \beta < 1 ,例如  0.9 ),它决定了之前梯度对当前更新的影响程度。
  • v_t 是前一步的动量值。
  • \nabla_{\theta} J(\theta_t) 是当前时间步  t  计算得到的梯度。
  • \theta_t 是当前模型参数。

参数更新方法如下

\theta_{t+1} = \theta_t - \eta v_{t+1}

其中

  • \theta_{t+1}是更新后的参数。
  • \theta_t 是当前的参数。
  • \eta 是学习率。
  • v_{t+1} 是当前的动量项(累积梯度)。

动量法的调用

动量法的调用一般集成在SGD优化器中,通过设置SGD优化器中的momentum参数来配置,momentum参数的值就是动量系数(平滑因子)

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torch.optim as optim

model = nn.Linear(5, 1)
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
print(model)
print(optimizer)

# Linear(in_features=5, out_features=1, bias=True)
# SGD (
# Parameter Group 0
#     dampening: 0
#     differentiable: False
#     foreach: None
#     fused: None
#     lr: 0.001
#     maximize: False
#     momentum: 0.9
#     nesterov: False
#     weight_decay: 0
# )

AdaGrad自适应梯度

AdaGrad(自适应梯度法)的作用是随着训练的进行,对学习率进行逐步衰减

累计梯度平方和

G_t = G_{t-1} + g_t^2

其中

  • G_t 是参数梯度平方的累积和(是一个对角矩阵,表示每个参数的梯度平方和)。
  • g_t  是当前时间步  t  的梯度
  •  G_{t-1}  是前面所有时间步的梯度平方和

参数更新方式

\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t} + \epsilon} \cdot g_t

其中

  • \theta_t 是当前的参数
  • \eta  是全局的学习率
  • G_t 是梯度平方的累积和
  • \epsilon  是一个小常数,用于防止除以零,通常取值为  10^{-8}

自适应梯度法的调用

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(10, 100)
        self.fc2 = nn.Linear(100, 5)
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

if __name__ == '__main__':
    my_net = SimpleNet()
    optimizer = optim.Adagrad(my_net.parameters(), lr=0.01)
    print(my_net)
    print(optimizer)

# SimpleNet(
#   (fc1): Linear(in_features=10, out_features=100, bias=True)
#   (fc2): Linear(in_features=100, out_features=5, bias=True)
# )
# Adagrad (
# Parameter Group 0
#     differentiable: False
#     eps: 1e-10
#     foreach: None
#     fused: None
#     initial_accumulator_value: 0
#     lr: 0.01
#     lr_decay: 0
#     maximize: False
#     weight_decay: 0
# )

RMSProp均方根传播法

RMSProp均方根传播法是在Adagrad的基础上做了优化,由于Adagrad中的累计平方和,会导致学习率快速下降导致模型收敛变慢

所以RMSProp对累计平方和进行了优化,转为了加权平均算法

梯度平方的指数加权平均算法

E[g^2]t = \beta E[g^2]{t-1} + (1 - \beta) g_t^2

其中

  • E[g^2]_t  是梯度平方的指数加权移动平均值(即该参数梯度的平滑历史平方值)
  • \beta  是衰减系数(通常取值接近 1,例如 0.9 或 0.99)
  • g_t  是当前时刻  t  的梯度
  • E[g^2]_{t-1}  是前一时刻的梯度平方的指数加权移动平均

参数更新

\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} \cdot g_t

其中

  • \theta_t  是当前的参数
  • \eta 是当前的学习率
  • E[g^2]_t 是梯度平方的指数加权移动平均
  • \epsilon  是一个小常数(通常取  10^{-8} ),用于防止除以零的情况

同时RMSProp也支持动量法用于记录历史梯度,但是与SGD中国的动量法有所不同

动量项 v_t 的更新

v_t = \beta v_{t-1} + \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} g_t

其中

  • v_t 是当前动量项
  • v_{t-1}  是前一时刻的动量项
  • \beta  是动量系数,通常接近 1(例如 0.9 或 0.99),表示过去动量的影响
  • \eta  是学习率
  • g_t 是当前的梯度
  • E[g^2]_t  是梯度平方的指数加权移动平均,用来动态调整每个参数的学习率

这里动量项的加入会使模型加快熟练

均方根传播法的调用

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(10, 100)
        self.fc2 = nn.Linear(100, 5)
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

if __name__ == '__main__':
    my_net = SimpleNet()
    optimizer = optim.RMSprop(my_net.parameters(), lr=0.01, alpha=0.99,momentum=0.9)
    print(my_net)
    print(optimizer)

# SimpleNet(
#   (fc1): Linear(in_features=10, out_features=100, bias=True)
#   (fc2): Linear(in_features=100, out_features=5, bias=True)
# )
# RMSprop (
# Parameter Group 0
#     alpha: 0.99
#     capturable: False
#     centered: False
#     differentiable: False
#     eps: 1e-08
#     foreach: None
#     lr: 0.01
#     maximize: False
#     momentum: 0.9
#     weight_decay: 0
# )

Adam自适应矩估计法

Adam自适应矩估计法,与RMSProp不同,其完整融合了Momentum和AdaGrad方法

一阶矩估计(动量)

  • m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t
  • m_t 是梯度的一阶矩的指数加权移动平均值(即动量)
  • \beta_1  是控制动量的衰减系数,通常取  0.9 
  • g_t  是当前时刻的梯度

二阶矩估计(梯度平方的指数加权移动平均)

  • v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2
  • v_t 是梯度平方的指数加权移动平均值(相当于 RMSProp 中的累积梯度平方)
  • \beta_2  是控制二阶矩的衰减系数,通常取  0.999 

一阶矩和二阶矩的偏差校正

由于一阶矩和二阶矩在初始化的时候,不具备前一时刻的动量,所以由于(1-衰减系数)的存在,刚开始的梯度下降幅度偏小,所以这里使用了偏差校正去放大一开始的下降幅度

  • \hat{m_t} = \frac{m_t}{1 - \beta_1^t}
  • \hat{v_t} = \frac{v_t}{1 - \beta_2^t}
  • \hat{m_t}  是一阶矩的偏差校正值
  • \hat{v_t}  是二阶矩的偏差校正值

参数更新

  • \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v_t}} + \epsilon} \hat{m_t}
  • \theta_t  是当前的参数
  • \eta  是学习率
  • \epsilon  是一个小常数,通常取  10^{-8} ,用于防止除以零的情况
  • \hat{m_t}  是偏差校正后的一阶矩
  • \hat{v_t}  是偏差校正后的二阶矩

参数设置说明

  • \beta_1  和  \beta_2 :分别控制一阶矩和二阶矩的衰减速率。通常推荐值为 \beta_1  = 0.9  和 \beta_2  = 0.999 
  • \epsilon :用于防止除以零的问题,保证数值稳定性,通常设置为  10^{-8} 
  • 学习率  \eta :这是 Adam 的全局学习率,通常设置为  0.001 
  • \beta_1^t  是  \beta_1  的  t  次方,随着迭代步数  t  的增加,\beta_1^t  趋近于 0,从而消除偏差

自适应矩估计法的调用

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(10, 100)
        self.fc2 = nn.Linear(100, 5)
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

if __name__ == '__main__':
    my_net = SimpleNet()
    optimizer = optim.Adam(my_net.parameters(), lr=0.01, betas=(0.9, 0.999), eps=1e-8)
    print(my_net)
    print(optimizer)

# SimpleNet(
#   (fc1): Linear(in_features=10, out_features=100, bias=True)
#   (fc2): Linear(in_features=100, out_features=5, bias=True)
# )
# Adam (
# Parameter Group 0
#     amsgrad: False
#     betas: (0.9, 0.999)
#     capturable: False
#     differentiable: False
#     eps: 1e-08
#     foreach: None
#     fused: None
#     lr: 0.01
#     maximize: False
#     weight_decay: 0
# )

补充

在以上四个优化器中,都支持配置weight_decay参数,其为正则化系数,添加后可以对模型添加L2正则

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

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

相关文章

定制化CRM如何重塑科技服务领域的生态链?

企业不仅面临着技术创新与知识产权保护的双重挑战&#xff0c;还需在激烈的市场竞争中构建稳固的客户关系与广泛的合作网络。传统的CRM&#xff08;客户关系管理&#xff09;系统&#xff0c;往往局限于企业内部的数据管理与流程优化&#xff0c;难以满足当前复杂多变的业务需求…

初识Linux · 进程替换

目录 前言&#xff1a; 1 直接看代码和现象 2 解释原理 3 将代码改成多进程版本 4 认识所有函数并使用 前言&#xff1a; 由前面的章节学习&#xff0c;我们已经了解了进程状态&#xff0c;进程终止以及进程等待&#xff0c;今天&#xff0c;我们学习进程替换。进程替换我…

【2023工业3D异常检测文献】Shape-Guided: 基于形状引导和双记忆库的异常检测方法

Shape-Guided Dual-Memory Learning for 3D Anomaly Detection 1、Background 提出了一个以形状为指导的专家学习框架&#xff0c;用于解决无监督3D异常检测的问题。 该方法建立在两个专门的专家模型及其协同作用的基础上&#xff0c;以从颜色和形状模态中定位异常区域。 第…

vue项目-仿知乎页面的路由跳转

这篇文章记录一下该项目的路由跳转&#xff0c;首先是登录页 登录页路由跳转到首页也就是index文件夹中 然后展示contentleft组件和contentright组件&#xff0c;他们在页面上的显示是这样的 然后每一个功能部分也会有另一个url&#xff0c;去跳转更详细的界面 有时间继续…

python-斐波那契词序列/最大回文乘积/求最大最小k个元素

一:斐波那契词序列题目描述 编写一个程序&#xff0c;生成斐波那契词序列的前n个元素。 斐波那契词序列是一个词序列&#xff0c;其中每个词是通过连接前两个词形成的。 它以斐波那契序列命名&#xff0c;因为它是以类似的方式创建的&#xff0c;但是我们不是加数字&#xff0c…

美国游戏玩家的文化偏好

美国游戏市场是世界上最大、最多样化的市场之一&#xff0c;受到一系列文化、社会和经济因素的影响。美国游戏玩家通常以参与技术和娱乐为特征&#xff0c;表现出由个人主义、竞争和社交互动驱动的偏好。主要趋势和偏好在这个市场中脱颖而出&#xff1a; 游戏类型多样 美国玩…

毕业设计选题:基于ssm+vue+uniapp的教学辅助小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

Resdis中关于字符串类型的基础命令

本文主要详解key-value中vaule为字符串类型的情况&#xff0c;value属于其他的数据类型不适应&#xff1b;有几个命令是通用命令 目录 1.set和get 2.keys 3.exists 4.del 5.expire 6.ttl 7.type 8.object encoding key 9.加减操作 10.字符串操作 11.命令小结 1.se…

拿下奇怪的前端报错:SyntaxError: Unexpected token ‘??=‘或‘xxx‘ - 浅谈Nodejs版本过高过低的部分问题

在前端开发时&#xff0c;如果同时维护多个项目&#xff0c;跨越的年度又比较大&#xff0c;难免会使用多个Nodejs版本。有时候版本不对&#xff0c;不仅仅是安装会报错 1 依赖无法安装 一般情况下nodejs又向后兼容较好&#xff08;除了部分三方包&#xff09;&#xff0c;所…

day03-js 作业

js基础 一.选择 1C 2C 3D 4C 5B 6B 7C 8A 二.编程 2 函数 数组与对象 一.选择 1D 2C 3D 4A 5D 6B 7B 8A 二.编程 1 2 4

Linux驱动开发(速记版)--设备树插件

第六十八章 设备树插件介绍 Linux 4.4之后引入了动态设备树&#xff0c;其中的设备树插件&#xff08;Device Tree Overlay&#xff09;是一种扩展机制&#xff0c;允许在运行时动态添加、修改或删除设备节点和属性。 设备树插件机制通过DTS&#xff08;设备树源文件&#xff0…

50.哀家要长脑子了!

1.1705. 吃苹果的最大数目 - 力扣&#xff08;LeetCode&#xff09; 贪心贪在哪里&#xff0c;用一个优先队列&#xff08;小根堆&#xff09;存储腐烂日期和该日期苹果腐烂的数量。优先吃掉距离腐烂日期最近的苹果。吃苹果分为两个阶段&#xff0c;第一个是在1-n天内&#xff…

MySQL 中的 LAST_INSERT_ID()函数详解

在 MySQL 数据库中&#xff0c;LAST_INSERT_ID()是一个非常有用的函数。它可以帮助我们获取最近一次插入操作所生成的自增 ID 值。本文将详细解释 MySQL 中的LAST_INSERT_ID()函数及其用途。 一、函数介绍 LAST_INSERT_ID()是 MySQL 中的一个内置函数&#xff0c;它返回最近一…

跨平台音乐播放器Feishin

什么是 Feishin &#xff1f; Feishin 是一款现代的自托管音乐播放器&#xff0c;支持多种音乐来源和功能。它是由Sonixd 的重构版本发展而来&#xff0c;能够与 Navidrome 或 Jellyfin API 音乐服务器兼容&#xff0c;目前还不支持 Subsonic API 。Feishin 具有现代化的用户界…

【mmsegmentation】Loss模块详解(入门)以调用FocalLoss为例

1、mmdet中损失函数模块简介 1.1. Loss的注册器 先来看段代码&#xff1a;mmseg/models/builder.py # mmseg/registry/registry.py # mangage all kinds of modules inheriting nn.Module # MODELS Registry(model, parentMMENGINE_MODELS, locations[mmseg.models])from mm…

风格迁移项目一:如何使用

前言 由于我不太会pr&#xff0c;所以直接新建的项目&#xff0c; 原项目地址&#xff1a;https://github.com/Optimistism/Style-transfer 原项目代码的讲解地址&#xff1a;https://www.bilibili.com/video/BV1yY4y1c7Cz/ 本项目是对原项目的一点点完善。 项目地址&…

C语言复习概要(一)

本文 C语言入门详解&#xff1a;从基础概念到分支与循环1. C语言常见概念1.1 程序的基本结构1.2 变量作用域和存储类1.3 输入输出1.4 编译与运行 2. C语言中的数据类型和变量2.1 基本数据类型2.2 变量的声明与初始化2.3 常量与枚举 3. C语言的分支结构3.1 if语句3.2 if-else语句…

Python笔记 - 函数、方法和类装饰器

前言 装饰器最早出现是Python2.4版本&#xff0c;为什么这个版本开始存在&#xff1f;这是因为最早标记类方法的做法是&#xff1a; def foo(self):perform method operation foo classmethod(foo)当方法体过长的时候很容易让人忽略掉最后的语句classmethod(foo)&#xff0c…

Win10之解决:设置静态IP后,为什么自动获取动态IP问题(七十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

域内密码喷洒 Password Spray 实验

password spray 1. 实验网络拓扑 kali: 192.168.72.128win2008: 192.168.135.129 192.168.72.139win7: 192.168.72.149win2012:(DC) 192.168.72.131 2. 简单原理 Kerberos针对同一个用户&#xff0c;多次的密码尝试请求有锁定保护策略。 但是我们可以切换用户&#xff0c;…