求导主要用到的方法是.requires_grad() ,将其设置为True则其相关的变量会构成一个求导网,记录其过程,这个方法会追踪记录定义在这个变量上的所有操作,然后调用.backward()就可以自动计算梯度,在这个Tensor上的所有梯度就会加进属性.grad中。代码实现:
构建的函数
y=f(x)=6x^2+2x+4 dy/dx=12x+2
import torch
import numpy as np
from IPython.display import Image
x=torch.tensor(3.,requires_grad=True)
print(x.data)#打印出数据
print(x.grad)#因为没有计算过程内容所以梯度为空
print(x.is_leaf)#是不是叶子节点(不依赖别的)
print(x.requires_grad)#是否需要计算梯度
tensor(3.)
tensor(38.)
True
True
y=6*x**2+2*x+4
##看一下y属性
print(y.data)#打印出数据
print(y.grad)#因为没有求,所以为空
print(y.is_leaf)#是不是叶子节点(有没有别的依赖)y依赖于x所以不是,是一个内部节点
print(y.requires_grad)#是否需要计算梯度(由x过来的所以需要计算)
tensor(64.)
None
False
True
求梯度:
y.backward()
print(x.data)#打印出数据
print(x.grad)#y对x求导38
print(x.is_leaf)#是不是叶子节点(不依赖别的)
print(x.requires_grad)#是否需要计算梯度
##############y对x求导38
######12*3+2=38
print("#########################y#######################")
print(y.data)#打印出数据
print(y.grad)#因为没有求,所以为空y式子里没有y
print(y.is_leaf)#是不是叶子节点(有没有别的依赖)y依赖于x所以不是,是一个内部节点
print(y.requires_grad)#是否需要计算梯度(由x过来的所以需要计算)
tensor(3.)
tensor(38.)
True
True
#########################y#######################
tensor(64.)
None
False
True
2,偏导:
函数式: f(u,v)=u^3+v^2+4uv p(f)/p(u)=3u^2+4v p(f)/p(v)=2v+4u
u=torch.tensor(3.,requires_grad=True)
v=torch.tensor(4.,requires_grad=True)
f = u**3 + v**2+4*u*v
f.backward()
print(u.grad)#27+16=43
print(v.grad)#8+12=20
tensor(43.)
tensor(20.)
构建计算图
连锁求导
l=f(g(h(x)))
import torch
a=torch.randn((3,3),requires_grad=True)
w1=torch.randn((3,3),requires_grad=True)
w2=torch.randn((3,3),requires_grad=True)
w3=torch.randn((3,3),requires_grad=True)
w4=torch.randn((3,3),requires_grad=True)
# b:3*3
b = w1*a
# c:3*3
c=w2*a
d=w3*b+w4*c
L=(10-d)
##粉色节点都是叶子节点
print(a.is_leaf)
print(w1.is_leaf)
print(w2.is_leaf)
True
True
True
print("############L的反向传播#############")
print(L)
L.backward()###注意,此处会报错,pytorch计算backward只能是个标量需要使用加和,取均值等操作
############L的反向传播############# tensor([[10.0803, 10.0628, 7.5192], [ 9.2849, 12.1867, 10.0175], [10.1017, 11.1517, 12.9821]], grad_fn=<RsubBackward1>)RuntimeError: grad can be implicitly created only for scalar outputs
因为后向求导仅仅针对标量,因此需要改为:
import torch
a=torch.randn((3,3),requires_grad=True)
print(a)
w1=torch.randn((3,3),requires_grad=True)
w2=torch.randn((3,3),requires_grad=True)
w3=torch.randn((3,3),requires_grad=True)
w4=torch.randn((3,3),requires_grad=True)
# b:3*3
b = w1*a
# c:3*3
c=w2*a
d=w3*b+w4*c
d.retain_grad()
L=(10-d).sum()#使用聚合函数
tensor([[ 0.9240, -0.1135, -0.8534],
[ 0.1692, -0.1923, -0.9745],
[ 0.2424, 0.2950, -0.9161]], requires_grad=True)
print("############L的反向传播#############")
print(L)
L.backward()
print(a.grad)
############L的反向传播#############
tensor(88.3535, grad_fn=<SumBackward0>)
tensor([[-2.9321, -0.5816, 1.0495],
[ 0.2598, 0.2794, -2.0839],
[-0.8607, 0.2975, 0.0086]])
-w3*w1-w4*w2
##与上式计算结果相同
tensor([[-2.9321, -0.5816, 1.0495], [ 0.2598, 0.2794, -2.0839], [-0.8607, 0.2975, 0.0086]], grad_fn=<SubBackward0>)
因为数学推导一致。