动手学深度学习 07

敖炜 Lv5

自动求导

向量链式法则

标量链式法则

标量链式法则

拓展到向量

向量链式法则
拓展到向量最大的问题是要把形状搞对

例1


此处X与W的内积对W求导,为符合分子布局,因此是

例2

自动求导

  • 自动求导计算一个函数在指定值上的导数
  • 它有别于
    • 符号求导(显式计算)
    • 数值求导

计算图

  1. 将代码分解成操作子
  2. 将计算表示成无环图
  3. 显式构造:MXNet/Tensorflow/Theano都可以显式的构造

  4. 隐式构造:Pytorch/MXNet

自动求导的两种模式

  • 链式法则
  • 方式一:正向累积
  • 方式二:反向累积、又称反向传递

例子

反向累积总结

  • 构造计算图
  • 前向:执行图,存储中间结果
  • 反向:从相反方向执行图
    • 去除不需要的枝

复杂度

  • 计算复杂度差不多
  • 反向累积的内存复杂度是O(n),需要存储正向的所有中间结果;正向的内存复杂度是O(1),但是通常在神经网络中不会用

自动求导实现

求导是几乎所有深度学习优化算法的关键步骤。深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。自动微分使系统能够随后反向传播梯度,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数

一个简单的例子

假设我们想对函数关于列向量求导。
首先,我们创建变量x并为其分配一个初始值。

1
2
3
4
5
6
7
import torch
x = torch.arange(4.0)
```
在我们计算y关于x的梯度之前,需要一个地方来存储梯度。重要的是,我们不会在每次对一个参数求导时都分配新的内存。因为我们经常会成千上万次地更新相同的参数,每次都分配新的内存可能很快就会将内存耗尽。
```python
x.requires_grad_(True) #等价于x=torch.arange(4.0, requires_grad=True)
x.grad #默认是None,以后可以通过这个访问梯度

现在计算y

1
y = 2 * torch.dot(x, x)

通过调用反向传播函数来自动计算y关于x每个分量的梯度,并打印他们

1
2
y.backward()
x.grad

现在计算x的另一个函数

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

非标量变量的反向传播

当y不是标量时,向量y关于向量x的导数的最自然解释是一个矩阵。对于高阶和高维的y和x,求导的结果可以是一个高阶张量。深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和

1
2
3
4
5
6
7
# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 本例只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad

分离计算

有时我们希望将某些计算移动到记录的计算图以外

1
2
3
4
5
6
7
x.grad.zero_()
y = x * x
u = y.detach() #将y视作一个常数而非与x相关的函数
z = u * x

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

Python控制流的梯度计算

使用自动微分的一个好处是:即使构建函数的计算图需要通过python控制流(例如条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度

1
2
3
4
5
6
7
8
9
10
11
12
13
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()

小结

  • 深度学习框架可以自动计算导数:我们首先将梯度附加到想要对其计算偏导数的变量上,然后记录目标之值的计算,执行它的反向传播函数,并访问得到的梯度

QA

  1. 为什么深度学习中一般对标量求导而不是对矩阵或者向量?
    因为loss和精度通常都是标量
  • 标题: 动手学深度学习 07
  • 作者: 敖炜
  • 创建于 : 2023-07-25 14:55:32
  • 更新于 : 2024-04-19 09:28:00
  • 链接: https://ao-wei.github.io/2023/07/25/动手学深度学习-07/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论