pytorch中backward函数的参数gradient作用的数学过程

2023-10-28 15:20

本文主要是介绍pytorch中backward函数的参数gradient作用的数学过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

pytorch中backward函数的参数gradient作用的数学过程

    • 问题描述
    • 实例分析

本机器学习小白最近在学习pytorch,在学习.backward()函数的过程中一直不能理解参数gradient的作用,感觉相关资料中对它的解释过于简单,几乎忽略了相关数学过程。这里分享一下我的理解,希望能对有需要的同学有些帮助。

.backward()函数是pytorch用来实现反向传播计算的关键,不了解反向传播或者.backward()函数的可以看看下面的文章:

  • pytorch中backward()函数详解
  • pytorch的计算图
  • PyTorch的自动求导机制详细解析,PyTorch的核心魔法
  • 反向传播——通俗易懂
  • 深度学习——以图读懂反向传播

问题描述

官方文档对.backward()的说明是这样的(看英文头痛的同学可以忽略解释内容):
在这里插入图片描述
gradient的解释是这样的:
在这里插入图片描述
可以粗浅的认为backward()就是在根据计算图计算tensor的“梯度”,但是这个“梯度”只有在tensor是标量(scalar)时才是真正意义上的梯度。

gradient在实际使用的过程中,是一个与使用.backward()的tensor维度一致的tensor。官方文档中只提到如果使用.backward()的tensor是一个标量,就可以省略gradient参数,而如果这个tensor是向量,则必须指明gradient参数,但这个参数对计算的作用是什么,文档中说的很模糊(好像就没提到)。

看了一些文章之后发现,“如果是(向量)矩阵对(向量)矩阵求导(tensor对tensor求导),实际上是先求出Jacobian矩阵中每一个元素的梯度值(每一个元素的梯度值的求解过程对应上面的计算图的求解方法),然后将这个Jacobian矩阵与grad_tensors参数对应的矩阵进行对应的点乘,得到最终的结果。”(来源:pytorch中backward()函数详解)
这里提到的grad_tensors参数就是现在的gradient参数。

所以本质上,gradient参数在向量与向量的求导中起作用,而backward()在这种情况下求得的各个元素的梯度实际上并不是Jacobian,而是Jacobian与gradient的乘积。

以下结合一些例子说明backward()函数的计算结果。

实例分析

来源:PyTorch的自动求导机制详细解析,PyTorch的核心魔法

import torchx = torch.tensor([0.0, 2.0, 8.0], requires_grad = True)y = torch.tensor([5.0, 1.0, 7.0], requires_grad = True)z = x * yz.backward(torch.FloatTensor([1.0, 1.0, 1.0]))

运行完之后查看z分别关于x和y的梯度可以发现:

>>>x.grad.data
tensor([5., 1., 7.])
>>>y.grad.data
tensor([0., 2., 8.])

实际上上述代码的计算结果可以这么理解:
x = ( x 1 x 2 x 3 ) = ( 0.0 2.0 8.0 ) y = ( y 1 y 2 y 3 ) = ( 5.0 1.0 7.0 ) x = \begin{pmatrix} x_1 & x_2 & x_3\end{pmatrix} = \begin{pmatrix} 0.0 & 2.0 & 8.0\end{pmatrix}\\ y = \begin{pmatrix} y_1 & y_2 & y_3\end{pmatrix} = \begin{pmatrix} 5.0 & 1.0 & 7.0\end{pmatrix} x=(x1x2x3)=(0.02.08.0)y=(y1y2y3)=(5.01.07.0) z z z向量则是 x x x y y y每项相乘得到的向量(不是点乘也不是叉乘)
z = ( x 1 y 1 x 2 y 2 x 3 y 3 ) z = \begin{pmatrix} x_1y_1 & x_2y_2 & x_3y_3\end{pmatrix} z=(x1y1x2y2x3y3)那么 z z z关于 x x x的Jacobian就是
J = ( ∂ z ∂ x 1 ∂ z ∂ x 2 ∂ z ∂ x 3 ) = ( ∂ z 1 ∂ x 1 ∂ z 1 ∂ x 2 ∂ z 1 ∂ x 3 ∂ z 2 ∂ x 1 ∂ z 2 ∂ x 2 ∂ z 2 ∂ x 3 ∂ z 3 ∂ x 1 ∂ z 3 ∂ x 2 ∂ z 3 ∂ x 3 ) = ( y 1 0 0 0 y 2 0 0 0 y 3 ) J=\begin{pmatrix} \frac{\partial z}{\partial x_1} & \frac{\partial z}{\partial x_2} & \frac{\partial z}{\partial x_3} \end{pmatrix} = \begin{pmatrix} \frac{\partial z_1}{\partial x_1} & \frac{\partial z_1}{\partial x_2} & \frac{\partial z_1}{\partial x_3} \\ \frac{\partial z_2}{\partial x_1} & \frac{\partial z_2}{\partial x_2} & \frac{\partial z_2}{\partial x_3} \\ \frac{\partial z_3}{\partial x_1} & \frac{\partial z_3}{\partial x_2} & \frac{\partial z_3}{\partial x_3} \end{pmatrix} =\begin{pmatrix} y_1 & 0 & 0\\ 0 & y_2 & 0\\ 0 & 0 & y_3 \end{pmatrix} J=(x1zx2zx3z)=x1z1x1z2x1z3x2z1x2z2x2z3x3z1x3z2x3z3=y1000y2000y3而我们引入的gradient参数是一个向量(这里用 v v v表示)
v = ( 1.0 1.0 1.0 ) T v = \begin{pmatrix} 1.0 & 1.0 &1.0 \end{pmatrix}^{T} v=(1.01.01.0)T然后将 J J J v v v相乘,我们就得到了我们看到的x.grad.data的结果:
J v = ( y 1 0 0 0 y 2 0 0 0 y 3 ) ( 1.0 1.0 1.0 ) = ( y 1 y 2 y 3 ) = ( 5.0 1.0 7.0 ) Jv =\begin{pmatrix} y_1 & 0 & 0\\ 0 & y_2 & 0\\ 0 & 0 & y_3 \end{pmatrix} \begin{pmatrix} 1.0 \\ 1.0 \\ 1.0 \end{pmatrix} = \begin{pmatrix} y_1 \\ y_2 \\ y_3 \end{pmatrix} = \begin{pmatrix} 5.0 \\ 1.0 \\ 7.0 \end{pmatrix} Jv=y1000y2000y31.01.01.0=y1y2y3=5.01.07.0y.grad.data的结果这里就不演示了,因为这个例子里 x x x y y y具有对称性,只需要把结果的 y y y换成 x x x就得到了y.grad.data的结果,所以我们可以看到x.grad.data和y.grad.data在数值上就是 y y y x x x的值。

这篇关于pytorch中backward函数的参数gradient作用的数学过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/294116

相关文章

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

JSON Web Token在登陆中的使用过程

《JSONWebToken在登陆中的使用过程》:本文主要介绍JSONWebToken在登陆中的使用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录JWT 介绍微服务架构中的 JWT 使用结合微服务网关的 JWT 验证1. 用户登录,生成 JWT2. 自定义过滤

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

css中的 vertical-align与line-height作用详解

《css中的vertical-align与line-height作用详解》:本文主要介绍了CSS中的`vertical-align`和`line-height`属性,包括它们的作用、适用元素、属性值、常见使用场景、常见问题及解决方案,详细内容请阅读本文,希望能对你有所帮助... 目录vertical-ali

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro