Pytorch学习记录-自动求导机制与张量操作规则

释放双眼,带上耳机,听听看~!
本文主要介绍了Pytorch的自动求导机制和张量操作规则,包括求导法则、Tensor张量操作规则以及如何计算梯度等内容。适合对Pytorch学习有兴趣的读者阅读。

pytorch学习记录

一、自动求导机制

参考:Pytorch的自动求导机制与使用方法(一) – 知乎 (zhihu.com)

​ 自动求导机制是pytorch核心功能之一。

1.1 求导法则

​ 限制:pytorch中默认只能是标量标量/向量/矩阵求导。

​ 即只能对f(x)=z,f:Rn→Rf(x)=z, f:R^nrightarrow R求导,其中xx可以通过多次复合函数得到,对ff求导利用链式法则:

∂z∂x=∂z∂y∂y∂xfrac{partial z}{partial x}=frac{partial z}{partial y}frac{partial y}{partial x}

​ 其中xx为叶节点,zz为根节点,yy是过程操作,并不会被收集,只是作一个传播作用。

​ pytorch中的求导法则,实则是反向传播。

1.2 Tensor张量操作规则

​ PyTorch中数据以张量(n维数组)的形式流动torch.Tensor可以用来创建张量。

​ 当Tensor的属性中requires_grad=True时,则系统就可以开始跟踪对此Tensor的所有操作。其中记录的每个操作求得的梯度不会保存,只有在最后的一个操作才会保存梯度。

​ 如上述的两次链式法则,只保存∂z∂xfrac{partial z}{partial x},而∂z∂yfrac{partial z}{partial y}只是被当作中间值,不会保存

​ 例:Tensor.backward()方法默认计算对计算图叶子节点的导数,中间过程的导数是不计算的

x = torch.tensor(3.0, requires_grad=True)
y = 2*x
z = y**2
f = z+2
f.backward()
print(x.grad)
print(y.grad)
print(z.grad)

​ 输出结果:

tensor(24.)
None
None

​ pytorch在求导时候会自动构建计算图。

Pytorch学习记录-自动求导机制与张量操作规则

​ 从上图可以看出,一个Tensor中:

  • data中保存着所存有的数据
  • grad中保存梯度
  • requires_grad表示是否开始追踪所有的操作历史

​ 想要计算梯度的时候,需要调用Tensor.backward()。在调用backward()时,只有当requires_grad和is_leaf同时为真时,才会计算节点的梯度值。

​ 例:pytorch只能标量对其他进行求导。

input:
import torch
x = torch.ones(2,2,requires_grad=True)
y = x+2# y 为非标量
print(x.is_leaf, y.is_leaf)
print(y.requires_grad)
y.backward()
ouput:
<<<True False
<<<True
<<<RuntimeError: grad can be implicitly created only for scalar outputs
    
# y为非标量,所以不符合y.requires_grad=True,所以无法求导

z = y * y * 3
out = z.mean()
print(out)
print(out.requires_grad)
out.backward()
print(x.grad)

output:
<<<tensor(27., grad_fn=<MeanBackward0>)
<<<True
<<<tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

​ 求导过程如下:

​ 令out=oout=o,由于

o=14∑zi=14∑3(xi)+2o=frac{1}{4}sum z_i=frac{1}{4}sum 3(x_i)+2

​ 所以

∂o∂xi∣xi=1=92=4.5frac{partial o}{partial x_i}|_{x_i=1}=frac{9}{2}=4.5

​ 例:对y=x3y=x^3,对x=2x=2进行求导

import torch
import torch.autograd

x = torch.tensor([2,0],requires_grad=True)
print("x= ",x)
print("x.requires_grad= ", x.requires_grad)
y = x ** 3
print("y= ",y)
print("y.requires_grad = ", y.grad_fn)

y.backward() #反向传播,求解导数
print("x.grad = ", x.grad)

​ 输出结果为:

x =  tensor([2.], requires_grad=True)
x.requires_grad =  True
y =  tensor([8.], grad_fn=<PowBackward0>)
y.requires_grad =  <PowBackward0 object at 0x7f3a1dac6320>
x.grad =  tensor([12.])

1.3 autograd类原理

​ autograd类的原理其实是利用雅可比矩阵进行计算。

​ 设函数f:Rn→Rmf:R^nrightarrow R^m,其中f=(f1,f2,…,fm)f=(f_1,f_2,dots,f_m),则雅克比矩阵为:

J=[∂f∂x1 ⋯ ∂f∂xn]=[∂f1∂x1⋯∂f1∂xn⋮⋱⋮∂fm∂x1⋯∂fm∂xn]J=left[ frac{partial f}{partial x_1} cdots frac{partial f}{partial x_n} right] =left[ begin{matrix}
frac{partial f_1}{partial x_1}& cdots& frac{partial f_1}{partial x_n}\
vdots& ddots& vdots\
frac{partial f_m}{partial x_1}& cdots& frac{partial f_m}{partial x_n}\
end{matrix} right]

​ 上面矩阵是ff关于x=(x1,…,xm)x=(x_1,dots,x_m)求导。

​ 令ll是一个标量函数,对ff进行求导有:

v=[∂l∂f1,∂l∂f2,⋯ ,∂l∂fm]v=[frac{partial l}{partial f_1},frac{partial l}{partial f_2},cdots,frac{partial l}{partial f_m} ]

​ 则llxx进行求导有:

dldx=J∗vTfrac{dl}{dx}=J*v^T

​ 其中对xix_i求偏导有:

∂l∂xi=v∗Jifrac{partial l}{partial x_i}=v*J_i

​ 其中JiJ_i表示JJ矩阵的第ii列。

​ 可以看到,l:Rm→Rl:R^mrightarrow R,从神经网络的例子来理解,ff是隐藏层为mm个神经元的个数,ll为输出层。

​ 从损失函数理解:标量ll类似于MSE函数将minibatch平均为一个平均loss上.

1.4 具体例子

标量对向量求导:

​ 令x=[x1,x2,x3]Tx=[x_1,x_2,x_3]^Tw=[w1,w2,w3]Tw=[w_1,w_2,w_3]^Ty=w∗x+by=w*x+b

​ 则偏导数为:

∂y∂x=[∂y∂x1,∂y∂x2,∂y∂x3]=[w1,w2,w3]frac{partial y}{partial x}=[frac{partial y}{partial x_1},frac{partial y}{partial x_2},frac{partial y}{partial x_3}]=[w_1,w_2,w_3]

x = torch.tensor([1.0,2.0,3.0], requires_grad=True)
w = torch.tensor([4.0,5.0,6.0], requires_grad=True)
b = 10
y = torch.dot(x,w)+b
y.backward()
print(x.grad)
print(w.grad)

output:
<<<tensor([4., 5., 6.])
<<<tensor([1., 2., 3.])

标量对矩阵求导:

​ 令X=[​x11x12x13​x21x22x23]X=left[ begin{matrix}{}
​ x_{11}& x_{12}& x_{13}\
​ x_{21}& x_{22}& x_{23}\
end{matrix} right]

​ 第一次操作:

Y=X+1=[x11+1×12+1×13+1×21+1×22+1×23+1]Y=X+1=left[ begin{matrix}{}
x_{11}+1& x_{12}+1& x_{13}+1\
x_{21}+1& x_{22}+1& x_{23}+1\
end{matrix} right]

​ 第二次操作:

Z=[z11z12z13z21z22z23]=[(y11)2(y12)2(y13)2(y21)2(y22)2(y23)2]Z=left[ begin{matrix}{}
z_{11}& z_{12}& z_{13}\
z_{21}& z_{22}& z_{23}\
end{matrix} right] =left[ begin{matrix}{}
left( y_{11} right) ^2& left( y_{12} right) ^2& left( y_{13} right) ^2\
left( y_{21} right) ^2& left( y_{22} right) ^2& left( y_{23} right) ^2\
end{matrix} right]

​ 第三次操作:

f=16sum(Z)f=frac{1}{6}sum(Z)

​ 偏导数为:

∂f∂xij=16∗2(∂(xij+1)2∂xij)=13(xij+1)frac{partial f}{partial x_{ij}}=frac{1}{6}*2(frac{partial(x_{ij}+1)^2}{partial x_{ij}})=frac{1}{3}(x_{ij}+1)

import torch
import torch.autograd

x = torch.tensor([[1.0,2.0,3.0],[4.0,5.0,6.0]], requires_grad=True)
y = x+1
z = y**2
f = torch.mean(z)

f.backward()
print(x.grad)

ouput:
<<<tensor([[0.6667, 1.0000, 1.3333],
        [1.6667, 2.0000, 2.3333]])

向量/矩阵对向量/矩阵求导:

​ 在pytorch中一般标量对向量或矩阵用的比较多,因为深度学习中最后的loss是输出一个值为标量,因此向量对矩阵求导需要传入一个梯度,即传入一个llff的求导得到的梯度。

​ 令x=[x1,x2,x3]x=[x_1,x_2,x_3]y=x∗2=[2∗x1,2∗x2,2∗x3]y=x*2=[2*x_1,2*x_2,2*x_3],此时对应上面1.3节有,y=(f1,f2,f3)y=(f_1,f_2,f_3),其中fi=2∗xif_i=2*x_i,所以有:

dydx=[∂f1∂x1∂f1∂x2∂f1∂x3∂f2∂x1∂f2∂x2∂f2∂x3∂f3∂x1∂f3∂x2∂f3∂x3]=[200020002]frac{dy}{dx}=left[ begin{matrix}
frac{partial f_1}{partial x_1}&frac{partial f_1}{partial x_2} & frac{partial f_1}{partial x_3}\
frac{partial f_2}{partial x_1} & frac{partial f_2}{partial x_2} &frac{partial f_2}{partial x_3} \
frac{partial f_3}{partial x_1}& frac{partial f_3}{partial x_2} & frac{partial f_3}{partial x_3} \
end{matrix} right] =left[ begin{matrix}
2&0 & 0\
0 & 2 &0 \
0& 0 &2\
end{matrix} right]

​ 传入:vvllff的梯度

v=[0.1,1.0,0.0001]v=[0.1,1.0,0.0001]

​ 例:

x = torch.randn(3, requires_grad=True)
y = x * 2
print(y)
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)

output:
<<<tensor([-0.1656,  1.2321, -3.1254], grad_fn=<MulBackward0>)
<<<tensor([2.0000e-01, 2.0000e+00, 2.0000e-04])

注意此处获得的梯度是llxx的梯度,而ll是没有显式的,因为只是传入了一个llff的梯度。

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

百度发布文心一言,对标ChatGPT,能力对比如何?

2023-12-21 19:19:14

AI教程

如何实现自定义图组件 in Rasa3

2023-12-21 19:32:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索