Pytorch中backward用法,以及gradient参数解析
标量函数backward
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
#反向传播
x = torch.ones(2, 2, requires_grad=True)
y = x + 2
z = y * y
out = z.mean()
# 如果没有下面这一行,x.grad=none
out.backward()
print("x.grad:{}\n".format(x.grad))
对于上面的例子,参数是x0,x1,x2,x3,假设我们把参数全部初始化为2,并且得到样本为2,2,2,2。
则本次迭代梯度计算的形式是\(out=\frac{1}{4} \sum_{i} z_{i}, z_{i}=\left(x_{i}+2\right)^{2}\)
根据链式求导法则可以求得out关于x0,x1,x2,x3的偏导数解析形式。
而backward()则是将样本值带入带入偏导数解析形式,求出数值上的偏导数。
向量函数backeward,及gradient参数解析
参考 https://zhuanlan.zhihu.com/p/65609544
下面举个栗子
一个分量函数为
\(\left\{\begin{array}{l}y_{1}=x_{1}^{2}+2 x_{2}+x_{3} \\ y_{2}=x_{1}+x_{2}^{3}+x_{3}^{2} \\ y_{3}=2 x_{1}+x_{2}^{2}+x_{3}^{3}\end{array}\right.\)
雅克比矩阵:
\(J=\left(\begin{array}{lll}\frac{\partial y_{1}}{\partial x_{1}} & \frac{\partial y_{1}}{\partial x_{2}} & \frac{\partial y_{1}}{\partial x_{3}} \\ \frac{\partial y_{2}}{\partial x_{1}} & \frac{\partial y_{2}}{\partial x_{2}} & \frac{\partial y_{2}}{\partial x_{3}} \\ \frac{\partial y_{3}}{\partial x_{1}} & \frac{\partial y_{3}}{\partial x_{2}} & \frac{\partial y_{3}}{\partial x_{3}}\end{array}\right)=\left(\begin{array}{ccc}
2 x_{1} & 2 & 1 \\
1 & 3 x_{2}^{2} & 2 x_{3} \\
2 & 2 x_{2} & 3 x_{3}^{2}
\end{array}\right)\)
在上面这个栗子中,对于参数x1, x2, x3的梯度,就要考虑y1, y2, y3三个函数分别对x1,x2,x3的偏导数。
那么怎么考虑呢,我们可以对这些偏导数分配权重,我们对y1,y2,y3的偏导数分配的权重值为(3,2,1)。则最后我们能得到分量函数y=(y1,y2,y3)关于(x1,x2,x3)的梯度(10,34,42):
\(v=(1,1,1)\)
\(v \circ J=\left[3 * 2 x_{1}+2 * 1+1 * 2,3 * 2+2 * 3 x_{2}^{2}+1 * 2 x_{2}, 3 * 1+2 * 2 x_{3}+1 * 3 x_{3}^{2}\right]=[10,34,42]\)
import torch
x1=torch.tensor(1, requires_grad=True, dtype = torch.float)
x2=torch.tensor(2, requires_grad=True, dtype = torch.float)
x3=torch.tensor(3, requires_grad=True, dtype = torch.float)
y=torch.randn(3) # produce a random vector for vector function define
y[0]=x1**2+2*x2+x3 # define each vector function
y[1]=x1+x2**3+x3**2
y[2]=2*x1+x2**2+x3**3
y.backward(torch.ones(3))
print(x1.grad)
print(x2.grad)