07 自动求导【动手学深度学习v2】

向量的链式法则在这里插入图片描述

例子在这里插入图片描述

在这里插入图片描述

自动求导

在这里插入图片描述
在这里插入图片描述

显示构造和隐示构造

显示构造 之后给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是标量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值