本文主要是介绍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=(∂x1∂z∂x2∂z∂x3∂z)=⎝⎜⎛∂x1∂z1∂x1∂z2∂x1∂z3∂x2∂z1∂x2∂z2∂x2∂z3∂x3∂z1∂x3∂z2∂x3∂z3⎠⎟⎞=⎝⎛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=⎝⎛y1000y2000y3⎠⎞⎝⎛1.01.01.0⎠⎞=⎝⎛y1y2y3⎠⎞=⎝⎛5.01.07.0⎠⎞y.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作用的数学过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!