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

自学

目录

1.两个例子

2.计算图概念

3.正向传播

4.反向传播

5.代码

(1). 基础例子:点积 + backward

(2). 清零梯度

(3). 元素平方

(4). 使用 .detach() 切断计算图

(5). Python 控制流里的梯度


1.两个例子

ps:

 转置符号没看懂原因:忘记了点积符号


2.计算图概念


3.正向传播

输入数据经过网络层层计算,得到输出

4.反向传播

利用链式法则,计算损失函数对参数的梯度,用来更新参数。


5.代码

手工求导:即把导数直接写出来

自动求导:pytorch自带函数

(1). 基础例子:点积 + backward



x = torch.arange(4.0)
x.requires_grad_(True)
 
y = 2 * torch.dot(x, x)   # y = 2*(0² + 1² + 2² + 3²) = 28
y.backward()
print(x.grad)   # tensor([ 0.,  4.,  8., 12.])

【1】requires_grad=True


x.requires_grad_(True)

作用:告诉 PyTorch 对这个张量 x 及其计算结果,追踪计算图,并能在 backward 时计算梯度。

_ 结尾说明它是 in-place 操作(直接修改 x 本身的属性)。

换句话说:

requires_grad=False(默认值):普通变量,不计算梯度。requires_grad=True:可训练变量,参与自动微分。

【2】backward的必要性


backward()
就是 触发反向传播的命令

前向传播只建图,不算梯度。

只有调用
backward()
,PyTorch 才会根据链式法则真正算出梯度,并存到
.grad

(2). 清零梯度



x.grad.zero_()
y = x.sum()
y.backward()
print(x.grad)   # tensor([1., 1., 1., 1.])

梯度是累加的,不是覆盖的

在 PyTorch 里,当你调用 backward() 时,计算出来的梯度会 累加 到 .grad 上,而不是直接替换

什么时候不需要清零?

如果 想要手动累加多个 batch 的梯度(比如梯度累积,显存不够时常用),那就不清零。

但在标准训练里,每个 batch 前都要清零

(3). 元素平方



x.grad.zero_()
y = x * x
y.sum().backward()
print(x.grad)   # tensor([0., 2., 4., 6.])

(4). 使用
.detach()
切断计算图



x.grad.zero_()
y = x * x
u = y.detach()   # u 不再跟踪梯度
z = u * x
z.sum().backward()
print(x.grad == u)   # True

(5). Python 控制流里的梯度



def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
 
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
 
print(a.grad == d / a)

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容