d2l - 自动微分 Day_3

本文最后更新于:1 年前

跟李沐学AI的第三天

0.引言

深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。实际中,根据设计好的模型,系统会构建一个计算图(computational graph),来跟踪计算哪些数据通过哪些操作组合起来产生输出。⾃动微分使系统能够随后反向传播梯度。这⾥,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。

1. 一个简单的例子

作为⼀个演⽰例⼦,假设我们想对函数y = 2x ^T^x关于列向量x求导。⾸先,我们创建变量x并为其分配⼀个初始值。

1
2
3
4
5
6
7
import torch

x = torch.arange(4.0)

x
OUT:
tensor([0., 1., 2., 3.])

计算y

1
2
3
4
y = 2 * torch.dot(x,x) #dot 计算向量点积
print(y)
OUT:
tensor(28., grad_fn=<MulBackward0>)

x是⼀个⻓度为4的向量,计算x和x的点积,得到了我们赋值给y的标量输出。接下来,通过调⽤反向传播函数来⾃动计算y关于x每个分量的梯度,并打印这些梯度。

1
2
y.backward()
print(x.grad)

函数y= 2x ^⊤^x关于x的梯度应为4x。让我们快速验证这个梯度是否计算正确。

1
2
3
x.grad == 4 * x
OUT:
tensor([True, True, True, True])

现在计算x的另一个函数

1
2
3
4
5
6
7
# 在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
x.grad.zero_()
y = x.sum()
y.backward()
print(x.grad)
OUT:
tensor([1., 1., 1., 1.])

2.非标量变量的反向传播

y不是标量时,向量y关于向量x的导数的最自然解释是一个矩阵。对于高阶和高维的yx,求导的结果可以是一个高阶张量。

然而,虽然这些更奇特的对象确实出现在高级机器学习中(包括深度学习),但当调用向量的反向计算时,我们通常会试图计算一批训练样本中每个组成部分的损失函数的导数。这里,我们的目的不是计算微分矩阵,而是单独计算批量中每个样本的偏导数之和。

1
2
3
4
x.grad.zero_()
y = x * x
y.sum().backward()
print(x.grad)

3.分离计算

有时,我们希望将某些计算移动到记录的计算图之外。例如,假设y是作为x的函数计算的,⽽z则是作为yx的函数计算的。想象⼀下,我们想计算z关于x的梯度,但由于某种原因,希望将y视为⼀个常数,并且只考虑到xy被计算后发挥的作⽤。这⾥可以分离y来返回⼀个新变量u,该变量与y具有相同的值,但丢弃计算图中如何计算y的任何信息。换句话说,梯度不会向后流经ux。因此,下⾯的反向传播函数计算z=u*x关于x的偏导数,同时将u作为常数处理,⽽不是z=x * x * x*关于x的偏导数。

1
2
3
4
5
6
7
x.grad.zero_()
y = x * x
u = y.detach() # 从 y 中分离出来的一个新变量 不具有y的关于x的计算图 后续求z的偏导时,将y当作一个常数
z = u * x

z.sum().backward()
print(x.grad == u)

由于记录了y的计算结果,我们可以随后在y上调⽤反向传播,得到y=x * x关于的x的导数,即2 * x

4.Python控制流的梯度计算

使⽤⾃动微分的⼀个好处是:即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调⽤),我们仍然可以计算得到的变量的梯度。在下⾯的代码中,while循环的迭代次数和if语句的结果都取决于输⼊a的值。

1
2
3
4
5
6
7
8
9
def f(a):
b = a*2
while b.norm() < 1000:
b *= 2
if b.sum() > 0:
c = b
else:
c = 100*b
return c

让我们计算梯度。

1
2
3
a = torch.randn(size=(),requires_grad=True)
d = f(a)
d.backward()

我们现在可以分析上⾯定义的f函数。请注意,它在其输⼊a中是分段线性的。换⾔之,对于任何a,存在某个常量标量k,使得f(a)=k * a,其中k的值取决于输⼊a,因此可以⽤d/a验证梯度是否正确。

1
a.grad == d/a

d2l - 自动微分 Day_3
https://wlpswmt.github.io/2023/03/22/d2l-自动微分/
作者
Sivan Zhang
发布于
2023年3月22日
许可协议