Pytorch 疑案之:优化器和损失函数是如何关联起来的?

损失函数与优化器:引导模型向正确方向发展 1.背景介绍 在机器学习和深度学习中,我们经常听到损失函数(Loss Function)和优化器(Optimizer)这两个词。它们是机器学习模型训练的核心组成部分,决定了模型的性能和效果。本文将详细介绍损失函数和优化器的概念,原理,以及如何在实际应用中使用它们。 2.核心概念与联系 阅读详情

疑问:

fc=torch.nn.Linear(n_features,1)
criterion=torch.nn.BCEWithLogitsLoss() # Loss 
optimizer=torch.optim.Adam(fc.parameters()) # optimizer 

for step in range(n_steps):
    if step:
        optimizer.zero_grad() # optimizer 
        loss.backward() # Loss  
        optimizer.step() # optimizer 
    
    pred=fc(x)
    loss=criterion(pred[train_start:train_end],y[train_start:train_end])

loss.backward()和optimizer.zero_grad()以及optimizer.step()到底做了什么?
这中间的迭代到底是怎样发生的呢?
从头开始,我们来分别搞懂这三个操作的含义

假如对一个函数进行求导数值

假设我们已知一个函数:f(x)=x3f(x)=x^3f(x)=x3,我们需要求 f′(4)=?f^{'}(4)=?f′(4)=?,我们通过口算知道:f′(x)=3x2f^{'}(x)=3x^2f′(x)=3x2,f′(4)=3∗42=48f^{'}(4)=3*4^2=48f′(4)=3∗42=48,那在torch里面应该怎样写呢?

torch里面有自动求导函数,用法代码如下:

import torch

def func(x):
    return x**3

x=torch.tensor([4],requires_grad=True,dtype=torch.float32) # 构建Tensor类
f=func(x) #把 Tensor 类作为参数传入
f.backward()
print(x.grad)

输出:

tensor([48.])

如上所见,利用 fffTensor.backward(),可以计算 f′(x)f^{'}(x)f′(x),结果储存在 xTensor.grad 对象里面。

(1)单位tensor 和 类Tensor 和构建函数torch.tensor()

单位 tensor:相当于一种最小的盛放数据容器。我们不可操作
类 Tensor:里面有几个或一个(大多数情况下)单位tensor,还带有其他函数属性,我们通过torch.tensor([]),torch.zeros()等函数返回的对象都是类Tensor

(2)Tensor.backward() 到底干了什么?

先来看有数据的自变量xxx:

当我们在使用torch.tensor()对 自变量xxx 进行构建的时候,曾经对参数requires_grad=True进行设置为True,意思就相当于说,这个Tensor类保留了一个盛放自己导数值的单位tensor。

我们可以这样抽象理解:
这个表示自变量xxx的Tensor类具有两个单位tensor,

  • 一个是主体的单位tensor:用于存放的是实实在在的这个自变量xxx的数值
  • 另外一个是辅助的单位tensor:用于存放的是这个自变量xxx被求导之后的导函数值

当我们通过一些正常手段(例如使用Tensor类的函数)进行操作的时候都是操作在主体那个单位tensor上,剩下那个辅助的单位tensor,我们可以通过x.grad来访问那个辅助的单位tensor。

如果自变量xxx不经过导数计算,x.grad是不会有数据的,你访问得到是None。
所以f.backward()所做的就是把导数值存放在x.grad里面。

需要注意的是x.grad不会自动清零的,他只会不断把新得到的数值累加到旧的数值上面,这就需要我们利用optimizer.zero_grad()来给他清零(后面会有更详细的说明)。

那问题来了,也没见f.backward()传什么参数呀?那它是怎样做到的呢?

再来看有数据的因变量fff

不知道你观察到没有,我这里和上面形容 x 和 f 都使用了“有数据”这个词语,因为无论是xxx还是fff,他们的type()出来都是一个Tensor类,他们在首次出现在代码的时候都是有数据的。自变量x的数据来自于我们构建的时候的赋值,而fff的数据在我们使用f=func(x)就确定了,而这也确定了xxx和fff作为Tensor类的不同性,因为fff是根据来自xxx的数据经过函数运算得到的。

输出fffTensor类会发现它的抽象数据结构如下:

  • 一个是主体的单位tensor:用于存放的是实实在在的这个因变量fff的数值
  • grad_fn:用于存放的是一个Function类,记录了主体的单位tensor的来源的计算历史

grad_fn存放的是计算历史,这就能理解为什么f.backward()能够求导了而且能够把结果直接操作到x.grad上了。

实际上,你会发现每一个Tensor类都能执行backward()函数,假如我们直接对自变量xTensor=[R]进行backward(),我们可以看到x.grad=[1],就相当于对它自己常数进行求导R′=1R^{'}=1R′=1

执行了backward()之后,不会对主体的单位tensor数值和自身的grad属性发生任何修改,fff和xxx自身的backward意义不同,我们是通过x→\rightarrow→f,既然他有上一级的Tensor,就会把backward()的结果存放在上一级的Tensor类的grad里面。由于x是被我们直接制造出来的root Tensor,x.backward()的结果存在自己的grad里面。

pytoch构建的计算图是动态图,为了节约内存,所以每次一轮迭代完也即是进行了一次backward函数计算之后计算图就被在内存释放,因此如果你需要多次backward只需要在第一次反向传播时候添加一个retain_graph=True标识,让计算图不被立即释放。

优化器optim类

我们对上面的代码进行改写:

import torch
import torch.optim

def func(x):
    return x**5 #x的5次方

x=torch.tensor([2],requires_grad=True,dtype=torch.float32)
optimizer=torch.optim.Adam([x,])

f=func(x)
optimizer.zero_grad() # 梯度清零
f.backward(retain_graph=True) #第一次反向传播,链式求导,retain_graph 为了不让计算图释放
optimizer.step() # 迭代更新
print(x.grad)

optimizer.zero_grad() # 梯度清零
f.backward() #第二次反向传播
optimizer.step() #迭代更新
print(x.grad)

输出:

tensor([80.])
tensor([79.8401])

(1)zero_grad() 到底干了什么?

我们前文提到过Tensor类的grad数值只会在原有基础上增加,自己是不会覆盖的,所以我们每计算一次就应该清零。实际上,zero_grad()做的就是一个清理工作。
如果我们把optim.zero_grad()换成x.grad=None,会发现得到一样的输出结果。

(2)step()函数到底干了什么?

首先,我们必须明白优化器是干什么的?现在我们有一个函数,我们现在需要到达一个谷点,也就是我们需要知道当函数在谷点的时候,自变量x到底等于多少,但是我们只能一个个点去尝试,所以我们必须要让梯度下降,也就是不断迭代x,每一次更换一次x的值,来促使梯度的值不断变小。

我们可以看回我们最基本的那个梯度下降算法:
θj:=θj−α∂J(θ0,θ1,θ2,...,θn)∂θj\theta_j:=\theta_j-\alpha\frac{\partial J(\theta_0,\theta_1,\theta_2,...,\theta_n)}{\partial\theta_j}θj​:=θj​−α∂θj​∂J(θ0​,θ1​,θ2​,...,θn​)​
而这个θ\thetaθ正是我们损失函数的自变量,所以我们在运算step()的时是参考了x.grad,也就是f.backward()的结果,这也就是为啥backward会先执行,再执行step。
那他参考这个grad是在哪里得到的呢?
我们在最开始初始化的时候就已经把自变量x托管给optim类了,无论是我们自己编写的函数,还是已经封装好的损失函数。也就是说我们的optim类只需要损失函数的自变量即可。
我们自己的函数使用优化器:

def func(x):
    return x**5 #x的5次方

x=torch.tensor([2],requires_grad=True,dtype=torch.float32)
optimizer=torch.optim.Adam([x,])

封装的损失函数使用优化器:

fc=torch.nn.Linear(n_features,1)
criterion=torch.nn.BCEWithLogitsLoss() # Loss 类
optimizer=torch.optim.Adam(fc.parameters()) # optimizer 类

我们已经知道weights,bias=fc.parameters(),对于损失函数而言,weights和bias就是他的自变量,所以这里用weights和bias来初始化优化器就能说得通了。

反正记住这样一点:所有的优化都是围绕损失函数来转的,我们想要损失降到最小,我们想要损失函数最小的时候的那个自变量的值,就是我们需要的权值。整个训练的过程就是在求权值的过程。
完整的逻辑过程:
在这里插入图片描述

最开始代码的注释

至此,我们给最开始的疑问代码打上注释:

fc=torch.nn.Linear(n_features,1) # 构建假设函数
criterion=torch.nn.BCEWithLogitsLoss() # 构建损失函数
optimizer=torch.optim.Adam(fc.parameters()) # 构建优化器(假设函数的权值)

for step in range(n_steps):
    if step:
        optimizer.zero_grad() # 梯度清零 weights.grad=None
        loss.backward() # 求出更新 weights.grad 的值
        optimizer.step() # optimizer # 根据新的 weights.grad 值更新迭代 weights 值
    
    pred=fc(x) #计算假设函数的值
    loss=criterion(pred[train_start:train_end],y[train_start:train_end]) #计算损失
探索loss.backward() 和optimizer.step()的关系并灵活运用 loss.backward() 和optimizer.step()的关系及灵活运用 在deep learning的模型训练中,我们经常看到如下的代码片段: loss.backward() optimizer.step() 那么,这两个函数到底是怎么联系在一起的呢? loss.backward()的作用 我们都知道,loss.backward()函数的作用是根据loss来计算网络参数的梯度,其对应的输入默认为网络的叶子节点,即数据集内的数据,叶子节点如下图所示: 同样的,该梯度信息也可以用函数torch. 阅读详情

相关推荐

深入解析BLheli电调固件与Dshot通讯协议:从原理到实践

本文深入解析了无人机动力系统的核心——BLheli电调固件与Dshot通讯协议。详细阐述了BLheli固件从经典版到BLheli_32的演进及其功能特性,并重点剖析了Dshot数字协议如何通过数据包和校验码实现更快、更准、更可靠的电机控制。文章还涵盖了双向Dshot遥测、实战配置与调参指南,帮助玩家充分释放无人机性能。

weixin_28273593的博客 434

损失函数与优化器的关联

import time # 在 GPU 上训练注意需要将网络和数据放到 GPU 上 net.to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() ...

shenjianhua005的专栏 3810

Zabbix监控网络设备讲解

Zabbix监控网络设备讲解 本人在研究学习zabbix的时候,网上找过很多如何监控路由,交换,或者是防火墙的文章,但很多都比较散,这里我出一个大概的整合,方便大家参考和学习。本章就拿华三的交换机来做文章。 监控网络设备首先我们需要开启snmp协议,华三怎么开启snmp协议在我的博客里有写到,其次就是找到版本对应的OID,zabbix就是通过抓取设备的OID来做到监控网络设备的,当然zabbix也不仅仅只有通过snmp来监控设备,还有很多别的功能,这些功能我会在以后的博客里面一一更新 文章目录Zab

太阳了文哥的博客 3381

pytorch-损失函数和优化器理解

pytorch损失函数优化器

THEENDOFTHEICE的博客 3617

Unity游戏开发客户端Unity基础

Unity游戏开发客户端面经 之 Unity 篇

Sea3752的博客 2万+

手把手教你设计STM32的JTAG电路:从原理图到PCB布局(含JLINK连接详解)

本文详细介绍了STM32的JTAG电路设计全流程,从核心原理、接口规范到PCB布局布线技巧,特别包含JLINK调试器的连接与配置方法。通过信号滤波、上拉配置和防反接保护等关键设计要点,帮助开发者构建稳定可靠的JTAG调试环境,提升嵌入式开发效率。

weixin_29159441的博客 388

损失函数和优化器

用于将梯度清零,pytorch不会自动清零梯度,所以每次更新前会进行该操作获取当前模型的当前参数,返回一个字典,key为各层参数名,value为参数值用于将state_dict 中的参数加载到当前网络,常用于迁移学习给 optimizer 管理的参数组中增加一组参数,可为该组参数定制 lr, momentum, weight_decay 等,在 finetune 中常用。执行一步权值更新, 其中可传入参数 closure(一个闭包)。如,当采用 LBFGS优化方法时,需要多次计算,

weixin_52366977的博客 1436

概率论基础-严士健 第二版 习题与补充1.6答案

概率论基础-严士健 第二版 习题与补充1.6答案 1.不独立。 设有一均匀正八面体,其第1,2,3,4面染红色,第1,2,3,5面染白色,第1,6,7,8面染黑色,现在以A,B,C分别表示投一次正八面体出现红、白、黑的事件,则 P(A)=P(B)=P(C)=12.P(A) = P(B) = P(C) = \frac{1}{2}.P(A)=P(B)=P(C)=21​. P(ABC)=18=P(A)P...

weixin_42341993的博客 2515

Pytorch内部中optim和loss是如何交互的

Pytorch内部中optim和loss是如何交互的? loss.backward()获得所有parameter的gradient。 然后optimizer存了这些parameter的指针,step()根据这些parameter的gradient对parameter的值进行更新。 optimizer = torch.optim.SGD(net.parameters(), lr=0.5) 这...

tyler的博客 783

数通基础(基本网络通信原理、IP地址如何配置、DHCP、DNS域名系统、路由技术基础、静态路由 、TCP和UDP、vlan虚拟局域网、trunk、三层交换)

我们知道了1、电脑开机,通过dhcp获取ip地址2、电脑输入域名,www.baidu.com电脑把www.baidu.com发到自己的dns服务器3、dns服务器把域名解析成对应的ip地址4、电脑向百度服务器发送一个请求。

qq_53235556的博客 6473

ESP32-C3模组上跑通OTA升级(3)

ESP32-C3模组上跑通OTA升级(3)

phmatthaus的专栏 1351

pytorch中网络loss传播和参数更新理解

相比于2018年,在ICLR2019提交论文中,提及不同框架的论文数量发生了极大变化,网友发现,提及tensorflow的论文数量从2018年的228篇略微提升到了266篇,keras从42提升到56,但是pytorch的数量从87篇提升到了252篇。 TensorFlow: 228--->266 Keras: 42--->56 Pytorch: 87--->252 在使...

771

飞牛fnNAS搭建web版微信

摘要:本文介绍了一种通过Docker在飞牛NAS上部署微信客户端的方法,实现24小时同步微信聊天记录。具体步骤包括:1)激活飞牛NAS的Docker功能并配置镜像加速源;2)创建专用文件夹并下载docker-wechat镜像;3)设置容器参数并部署微信客户端;4)通过局域网或ZeroTier内网穿透实现远程访问。相比传统Windows/Linux方案,该方法资源占用更低,适合需要长期保存微信聊天记录的用户。

dgnankai的专栏 3330

pytorch中优化器和学习率衰减方法总结

torch.optim torch.optim是一个实现了各种优化算法的库。大部分常用的方法得到支持,并且接口具备足够的通用性,使得未来能够集成更加复杂的方法。 如何使用optimizer 为了使用torch.optim,你需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。 构建 为了构建一个Optimizer,你需要给它一个包含了需要优化的参数(必须都是Variable对象)的iterable。然后,你可以设置optimizer的参数选项,比如学习率,权重衰

ddana_a的博客 3924

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

4_损失函数和优化器

常见的损失函数包括均方误差(Mean Squared Error, MSE)、交叉熵损失(Cross Entropy Loss)、对数损失(Log Loss)等,具体选择哪种损失函数取决于问题的类型和输出的形式。在监督学习任务中,我们通常希望模型的预测尽可能接近真实的目标值。反向传播是一种有效的训练神经网络的方法,它利用链式法则计算损失函数对每个模型参数的梯度,并根据梯度更新参数。用于优化神经网络模型的库,它的主要作用是实现各种优化算法,帮助模型在训练过程中更新参数以最小化损失函数。有需要可以自己查用法。

m0_74357009的博客 1385

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

优化函数和损失函数的区别与联系

优化函数和损失函数的区别与联系

Le0v1n 的博客 3276

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

深度学习笔记(五)---损失函数与优化器

以下笔记来源: [1] . 《pytorch深度学习实战》 [2] .pytorch 损失函数总结 (https://blog.youkuaiyun.com/jacke121/article/details/82812218) [3] .PyTorch学习之十种优化函数(https://blog.youkuaiyun.com/shanglianlm/article/details/85019633) ...

一一 1万+

损失函数、梯度下降、优化器

优化器

weixin_44986037的博客 1200

损失函数loss和优化器optimizer

它是必要的,因为PyTorch默认会在反向传播过程中累积梯度,如果不清零,梯度将会累积在后续迭代中,导致结果不正确的参数更新。我们在计算 loss = criterion(out, input)时,这里的out就等于y就等于w1X1+w2X2+w3X3,(虽然y是一些具体的值,但是这些值是由w1X1+w2X2+w3X3构成的),所以。,这里面的参数就是tensor,其有两个地址,分别存放当前值和反向求导的值,loss.backward()后,这个时候就每个参数里面都有导数,然后。

zhu_ba的博客 726

深度学习中模型、损失函数与优化器的协作机制详解

一、核心概念对应关系在机器学习理论体系中,存在模型、策略、算法三大核心要素,而在深度学习的具体实现中,它们分别对应神经网络结构、损失函数、优化器。二、三者协作流程详解。

Kent_Li的博客 1173

优化器、反向传播、损失函数之间是什么关系,Pytorch中如何使用和设置?

PyTorch模型训练的核心闭环由损失函数、反向传播和优化器组成,形成"五步走"标准流程:1)定义损失函数和优化器;2)前向传播计算预测;3)计算损失值;4)梯度清零后反向传播;5)优化器更新参数。损失函数评估误差,反向传播计算梯度,优化器调整参数,三者协作不断优化模型。关键代码模板包括loss.backward()计算梯度和optimizer.step()更新参数,通过循环迭代逐步降低损失值,实现模型训练目标。

学无止境,止于至善 1168

mindspore中两个网络,用它们损失函数的和来优化

问题描述:想咨询一下,就是我有两个网络net1,net2,定义了损失函数是loss1+loss2,怎么同时用这一个loss优化这两个网络?应该如何定义我的TrainOneStepCell?看这个定义好像只支持一个network啊。这怎么办? 解答:将两个前向net,两个loss计算,以及loss求和封装为一个network。 两个loss求和: https://mindspore.cn/docs/programming_guide/zh-CN/r1.6/loss.html#%E5%AE%9A%E4%B9%8

weixin_45666880的博客 478

【PyTorch】第五节:损失函数与优化器

在上一节实验中,我们初步完成了梯度下降算法求解线性回归问题的实例。在这个过程中,我们自己定义了损失函数和权重的更新,其实PyTorch 也为我们直接定义了相应的工具包,使我们能够简洁快速的实现损失函数、权重的更新和梯度的求解。

荷叶田田的博客 1026

pytorch损失函数、反向传播、优化器【小土堆】

(链接可以直接跳转)

superiser的博客 2019

backward理解

backward:自动求梯度。计算小批量随机梯度。 当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解 叫作解析解(analytical solution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数 深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。 在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient d

weixin_38383877的博客 3018

backward 最好的解释

outputs : 函数的因变量,即需要求导的那个函数,在本例子中,为z,当然,他可以是一个tensor,也可以是几个tensor,如[tensor1,tensor2,tensor3...]inputs : 函数的自变量,在本例中,即对应的是[x,y],他可以是一个tensor,也可以是几个tensor,如[tensor1,tensor2,tensor3...]grad_output : 这个参数和前面两种方法中的grad_tensors是同样的含义,当出现向量对向量求导的时候需要指定该参数。

蜗牛在奔跑的博客 1220
上一篇: Pytorch 线性回归(下)【Pytorch 基础第四话】
下一篇: RoboMaster 目标检测训练(官方数据集)附完整Demo代码
JintuZheng
博客等级 码龄11年 1483粉丝 109原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值