向量的链式法则
例子
自动求导
显示构造和隐示构造
显示构造 之后给a和b传入值 类似公式代入一样 先给公式定义 再传值
隐示构造
链式法则中求导:正向和反向
对于链式公式
正向:从后往前 向前
反向:从前往后 想后
自动求导
import torch
x = torch.arange(4.0)
x.requires_grad_(True)# 等价x = torch.arange(4,requires_grad=True) 等于True是需要存储梯度
print(x)
print(x.grad)# 默认是None
y = 2 * torch.dot(x,x)
print(y)
'''
tensor([0., 1., 2., 3.], requires_grad=True)
None
显示构造
tensor(28., grad_fn=<MulBackward0>)
28=2*(0^1+1^2+2^2+3^2)
'''
# 调用反向传播来计算y对x每个分量的梯度
print(y.backward())
print(x.grad)
print(x.grad == 4 * x)
'''
None
tensor([ 0., 4., 8., 12.])
tensor([True, True, True, True])
'''
# pytorch中会累积梯度 我们需要清除之前的值
print('x:',x)
x.grad.zero_()
y = x.sum()# 等价于x1+...+xn 然后对xi求导 所以求导结果是常数1
print('y:',y)
y.backward()
print('x.grad:',x.grad)
'''
x: tensor([0., 1., 2., 3.], requires_grad=True)
y: tensor(6., grad_fn=<SumBackward0>)
x.grad: tensor([1., 1., 1., 1.])
'''
大部分我们都是对标量求导
# pytorch中会累积梯度 我们需要清除之前的值
print('x:',x)
x.grad.zero_()
y = x*x
print('y',y)
u = y.detach() # u变成常数 与x无关
print('u',u)
z = u*x
z.sum().backward()
print(x.grad == u)
'''
x: tensor([0., 1., 2., 3.], requires_grad=True)
y tensor([0., 1., 4., 9.], grad_fn=<MulBackward0>)
u tensor([0., 1., 4., 9.])
tensor([True, True, True, True])
'''
y.sum().backward()和y.backward()的区别
y.backward() 是因为之前的
y = 2 * torch.dot(x,x) tensor(28., grad_fn=<MulBackward0>)
已经求和过了
y是个标量
因此当输出不是标量时,调用.backwardI()就会出错
x = torch.arange(4.0)
x.requires_grad_(True)# 等价x = torch.arange(4,requires_grad=True) 等于True是需要存储梯度
print(x)
print(x.grad)# 默认是None
y = 2 * torch.dot(x,x)
print(y)
'''
tensor([0., 1., 2., 3.], requires_grad=True)
None
显示构造
tensor(28., grad_fn=<MulBackward0>)
28=2*(0^1+1^2+2^2+3^2)
'''
x.grad.zero_()
y = x*x
print('y',y)
y.sum().backward()
print(x.grad == 2*x)
'''
None
tensor([ 0., 4., 8., 12.])
tensor([True, True, True, True])
'''
torch会把计算图存下来然后再倒着推一遍
import torch
def f(a):
b = a*2
while b.norm()< 1000:
b = b*2
if b.sum()> 0:
c = b
else:
c = 100*b
print('a,b,c',a,b,c)
return c
# size=()表示标量
a = torch.randn(size=(), requires_grad=True)
print(a)
d = f(a)
print('d.backward()', d.backward())
print('a.grad', a.grad)
print(a.grad == d/a)
'''
tensor(0.8685, requires_grad=True)
a,b,c tensor(0.8685, requires_grad=True) tensor(1778.7827, grad_fn=<MulBackward0>) tensor(1778.7827, grad_fn=<MulBackward0>)
d.backward() None
a.grad tensor(2048.)
tensor(True)
'''
问题解答:
显示构造不方便
在神经网络中正向和反向都需要算一遍(但正的会帮你算)
pytorch会默认累积梯度
loss是标量