pytorch的梯度图与autograd.grad和二阶求导

前向与反向


  • 这里我们从 一次计算 开始比如 z=f(x,y) 讨论
  • 若我们把任意对于tensor的计算都看为函数(如将 a*b(数值) 看为 mul(a,b)),那么都可以将其看为2个过程:forward-前向,backward-反向
  • 在pytorch中我们通过继承torch.autograd.Function来实现这2个过程,详细的用法和扩展参考:https://pytorch.org/docs/stable/notes/extending.html
  • 【例子】比如我们要实现一个数值乘法z= ( x ∗ y ) 2 (x*y)^2 (xy)2

前向

  • 在前向过程中,我们主要干的事情为:1. 通过输入计算得到输出。2.保存反向传播求导数所需要的tensor到ctx(在反向传播的时候会对应的传入)
  • 【例子】1.为了反向传播求梯度保存x,y(因为我们知道 d z / d x = 2 ∗ x ∗ y 2 , d z / d y = 2 ∗ y ∗ x 2 dz/dx=2*x*y^2, dz/dy=2*y*x^2 dz/dx=2xy2,dz/dy=2yx2), 2.return ( x ∗ y ) 2 (x*y)^2 (xy)2

反向

  • 在反向传播的时候我们干的事情就是,将传入的导数(梯度)和我们在前向过程中保存的tensor进行加工,最终返回每个输入变量的梯度
  • 【例子】此时反向时应该返回 2 ∗ x ∗ x ∗ y 与 2 ∗ x ∗ y ∗ y 2*x*x*y与2*x*y*y 2xxy2xyy,分别对应 d z / d x , d z / d y dz/dx, dz/dy dz/dx,dz/dy

计算图


  • 那么对于一次计算的讨论完了,现在我们来讨论多次计算,即梯度(导数)是如何一步步的从最终的z=f(a), a=g(b), b=w©… 一层层的 传回x的。
  • 那么在pytorch中,其使用了图的数据结构,在一开始 z = x ∗ x ∗ y ∗ y z=x*x*y*y z=xxyy的例子中,z会指向x与y,方便反向传播求梯度(导数),现在若 w = z ∗ z w=z*z w=zz(关于z的函数),那么w会指向z
  • 那么 d w / d x = d w / d z ∗ d z / d x dw/dx = dw/dz * dz/dx dw/dx=dw/dzdz/dx
  • 在这里插入图片描述

需要梯度?,require_grad

  • 但是很多tensor在计算时是不需要梯度的,而保存上面那种梯度图又很费空间,pytroch默认你创建的tensor是不需要梯度的
  • 如当你使用线性层时,实际上是 w ∗ x + b w*x+b wx+b,但是其实这里传入x是需要梯度的(它又不需要学习),而w与b是模型的参数是nn.Parameters,所以他需要学习,自然需要梯度,
  • 而这里pytorch就使用一个bool标记来说明这个tensor需要梯度嘛,若他需要梯度,那么基于他的计算才会有指针指向它
  • 比如, z = x ∗ y z=x*y z=xy,若x,y都require_grad=False,则根本不会建立计算图,若x的requires_grad=True,则该计算会建立z->x的计算图

梯度函数,grad_fn

  • 当你进行了建立了计算图的计算,比如x.requires_grad=True, z = x ∗ y z=x*y z=xy, 那么z.grad_fn就会有函数指针指向反向传播的计算,这里就是这个 x ∗ y x*y xy
  • 在上图中一个节点虽然向回指向多个变量,但其实对应函数指针,其实是指向一个函数 x ∗ x ∗ y ∗ y x*x*y*y xxyy,2个箭头对应的是2个返回值 ( d z / d x , d z / d y ) (dz/dx,dz/dy) (dz/dx,dz/dy),函数指针可以在运算完了后在tensor.grad_fn看到

梯度,grad

  • 当你在正向计算时,构建完了上述的这样一个计算图,你就可以对最终得到的tensor调用backward函数,那么整个计算图就会从最后一个变量还是反向一步一步的将梯度传给每个需要保存梯度的tensor,这时可以在tensor.grad中看到,此时默认情况tensor.grad_fn会被清空。

torch.autograd.grad


  • 大部分情况下,我们都是得到loss,然后loss.backward(),模型的参数对应的每个tensor就会的到梯度,这个时候opt.step()就会根据学习率优化参数
  • 但有时候我们需要手动求导,可以使用 torch.autograd.grad函数

自变量,input

  • x,即对什么求导,当然该tensor必须requires_grad=True,在因变量的同一梯度图的后继

因变量,output

  • y,即被求导的变量,这里结合x相当于求dy/dx

加权,grad_outputs

  • pytorch中求导的因变量必须是一个shape为[1]的tensor,所以比如当backward时,我们往往取loss.sum() 或者mean(), 那么这里y是个大小不定的tensor,那么这个参数就是和y的shape一样,先令(g代表grad_outputs) L = ∑ g i j ∗ y i j L=∑g_{ij}*y_{ij} L=gijyij, 然后L在对x求导,这里求和往往我们取g=torch.ones_like(y), 相当于y.sum()
  • 一般情况下,不同batch之间的计算是独立的,所以得到的y就算sum后,每个x的得到的梯度其实是batch独立的,但是batch_norm除外,因为batch_norm,不同batch的x会与整个batch的均值做运算, 除非你手写batch_norm,并将数据均值对应的tensor mu detach掉,此时mu对于整个梯度图就是一个常数,否则mu会指向不同batch的x,导致每个x的得到的梯度其实不是batch独立的

输出

  • 输出的shape和x一样,即最终的L对于x每个位置的梯度,这也同样解释了为什么必须要对y求和得L,否则每个x中的每个位置其实对应整个tensor,y

二阶求导,create_graph

  • 那么若想二阶求导,我们举个例子z = f(x,y) , z1 = ∂f/∂x, z2 = ∂z1 / ∂y,在代码里,其实x对应X[:,0], y对应X[:,1](也可以其他对应),其实还是一个tensor
  • 那么首先把torch.autograd.grad整个过程又看为一次新的计算,在反向求导求z1时,程序会按照上述过程一步一步反向传播,而反向传播得到梯度时,其实这里又可以形成新的梯度图,z1处于整个新的梯度图顶端
  • 那么对应代码里,使用函数参数create_graph=True来告诉autograd,我这次得到的tensor是需要产生梯度图的(因为可能进一步求导)
  • 那么在代码里,我们相当于
 z1 = torch.autograd.grad(output=y,input=X,...)[0][:, 0]
 z2 = torch.autograd.grad(output=z1,input=X,...)[0][:, 1]
 
若你的输入X是将x与y合成一体的,如x=X[:,0], y=X[:,1],那么你求导也只能将整体X作为输入,再从答案中获得对应的列
若你直接在求导时input=X[:,i] 这里实际上你创建了一个新tensor X[:,i] -> X, 而Z->X, 并未指向X[:,i], 故不行

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

目录 简介 原理分析 EXP 前文:【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下,这个C3P0的Gadget可以和fastjson,Snake YAML , JYAML,Yamlbeans , …

【Javascript编程实操05】1、小明买洗发水、香皂、牙刷组合 2、利用循环写出100以内的奇数的和及偶数的和

前言 1、小明买洗发水、香皂、牙刷组合 代码: 实现效果: 2、利用循环写出100以内的奇数的和及偶数的和 代码: 实现效果: 总结 前言 本次主要是继续针对Javascript阶段的for循环的实操练习,共有2个实操&#xff…

vscode setting.json 全局设置 工作区设置 位置 优先级

vscode中setting.json有两种配置权限 一、全局配置:setting.json文件位于C:\Users\Administrator\AppData\Roaming\Code\User\settings.json 二、工作区配置:setting.json文件位于工作区的.vscode\settings.json 当两种配置同时存在时,工作区…

单链表详解(如何实现单链表)

文章目录 前言 一、单链表是什么?二、单链表的实现总结 顺序表的缺点 1.中间/头部的插入删除,时间复杂度为O (N) 2.realloc 扩容(特别是异地扩,需要申请新空间,拷贝数据,释放旧空间)会有不小的…

【开源】JAVA+Vue.js实现高校宿舍调配管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统展示四、核心代码4.1 查询单条个人习惯4.2 查询我的室友4.3 查询宿舍4.4 查询指定性别全部宿舍4.5 初次分配宿舍 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的…

Day24:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

目录 文件管理模块-上传-过滤机制 文件管理模块-显示-过滤机制 思维导图 PHP知识点 功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出&#…

泛微OA服务器获取 token

泛微OA服务器获取 token 文章目录 泛微OA服务器获取 token一、泛微官方方法1 ecology 系统配置2 发放/生成许可证(appid)3 限制许可证使用ip地址(该步骤也可以跳过)4 使用 postman 注册5 获取 token6 访问业务系统接口 二、java 代码获取 token三、封装到…

【Redis项目实战】使用Springcloud整合Redis分布式锁+RabbitMQ技术实现高并发预约管理处理系统

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏带你Redis从入门到入魔 这是苏泽的个…

一次生产环境上的dockerd启动失败原因分析

今夜原计划对 生产环境 上的 SDN 组件进行一次紧急扩容操作的,但业务基础环境中的 Docker-Engine 启动不起来了、原定计划也就无法继续进行了。 尽管查清了基础业务环境中的故障原因,但金主DD说今天先不干了,那就整理整理思路写篇流水账吧 。…

Linux环境下使用线程方式操作UART读写功能

目录 概述 1 Linux环境下UART设备 2 轮询方式操作UART功能实现 2.1 打开串口函数:usr_serial_open 2.2 关闭串口函数: usr_serial_close 2.3 发送数据函数: usr_serial_sendbytes 2.4 接收数据函数: thread_uart_readbytes …

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文:https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译:OneBlock 区块链领域不断发展,随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

生态,带给用友新机会? | ToB产业观察

ITValue 近年来,不少厂商都将生态调整到战略级别,但做生态往往需要实打实、接地气的生态策略。 作者|杨丽 首发|钛媒体APP ITValue 3月初,用友召开了新一年的首场生态发布会,为接下来一年动作定调&#xff…

17、电源管理入门之Power supply子系统

目录 1. Power supply框架都做些什么 2. 相关数据结构和接口 2.1 数据结构 2.2 接口 3. 充电驱动 3.1 Charger Manager 3.2 Fuel Gauge 3.3 Charger IC 4. 怎样基于power supply class编写PSY driver 参考资料: 对于便携设备来说,电源管理更加的重要,因为电池电量…

数据库系统概念(第一周)

⚽前言 🏐四个基本概念 一、数据 定义 种类 特点 二、数据库 三、数据库管理系统(DBMS) 四、 数据库系统(DBS) 🏀数据库系统和文件系统对比 文件系统的弊端 🥎数据视图 数据抽象 …

jeecgboot 新建子模块 使用@EXCEL实现实现导入导出功能

一,用框架生成增删改查模块 二,在实体类entity 需要导入导出的字段上加上注解Excel 三,在controller类上继承jeecgboot通用controller JeecgController 并且在JeecgController里增加导出模板的方法 /*** 导出excel空模板** param req…

融资项目——网关微服务

1. 网关的路由转发功能 在前后端分离的项目中&#xff0c;网关服务可以将前端的相关请求转发到相应的后端微服务中。 2. 网关微服务的配置 首先需要创建一个网关微服务&#xff0c;并添加依赖。 <!-- 网关 --><dependency><groupId>org.springframework.cl…

相似矩阵及其对角化

目录 相似矩阵 矩阵的相似对角化 对称矩阵的相似对角化 相似矩阵 矩阵的相似对角化 对称矩阵的相似对角化

循序渐进丨MogDB 数据库新特性之SQL PATCH绑定执行计划

1 SQL PATCH 熟悉 Oracle 的DBA都知道&#xff0c;生产系统出现性能问题时&#xff0c;往往是SQL走错了执行计划&#xff0c;紧急情况下&#xff0c;无法及时修改应用代码&#xff0c;DBA可以采用多种方式针对于某类SQL进行执行计划绑定&#xff0c;比如SQL Profile、SPM、SQL …

鸿蒙实战多媒体运用:【音频组件】

音频组件用于实现音频相关的功能&#xff0c;包括音频播放&#xff0c;录制&#xff0c;音量管理和设备管理。 图 1 音频组件架构图 基本概念 采样 采样是指将连续时域上的模拟信号按照一定的时间间隔采样&#xff0c;获取到离散时域上离散信号的过程。 采样率 采样率为每…

macos m1 arm芯片 使用jpype报错 FileNotFoundError: [Errno 2] JVM DLL not found

startJVM(jpype.getDefaultJVMPath()) 报错 Traceback (most recent call last):File "/Users/thomas990p/PycharmProjects/tuya/volcano-biz-scripts/WenKongFa/FinalCode/java2python/CallJavaAPI.py", line 12, in <module>startJVM(jpype.getDefaultJVMPa…