梯度
将一个多元函数对其所有变量的偏导数连结一起,我们能够得到该函数的梯度(gradient)向量。
设函数f:Rn→R ,其输入为n 维向量x=[x1,x2,...,xn]T,输出是一个标量。
则函数y=f(x) 对于x 的梯度,是一个包含n 个偏导数的向量:
∂x∂y=[∂x1∂y,∂x2∂y,⋯,∂xn∂y]T
标量对向量的求导
假设x 为n 维向量,y 、a均为标量,则在多元微分函数常使用以下规则:
| y | a | au | sum(x) | ∣x∣2(十分常用!) |
|---|
| ∂x∂y | 0T | a∂x∂y | 1T | 2xT |
| y | u+v | uv | <u,v> |
|---|
| ∂x∂y | ∂x∂u+∂x∂v | ∂x∂uv+∂x∂vu | uT∂x∂v+vT∂x∂u |
<u,v> 的含义,即为两个向量u、v 进行内积运算
向量对向量的求导
假设x 为n 维向量,y 为m 维向量函数,则∂x∂y 为m×n 的矩阵
其具体的表达式为:
∂x∂y=∂x∂y1∂x∂y0⋮∂x∂ym=∂x1∂y1,∂x2∂y1,⋯,∂xn∂y1∂x1∂y2,∂x2∂y2,⋯,∂xn∂y2⋮∂x1∂ym,∂x3∂ym,⋯,∂xn∂ym
下列表格中,a 是与x 无关的标量,a 是与x 无关的向量,A 是与x 无关的矩阵,
| y | a | x | Ax (十分常用) | xTA (十分常用!) |
|---|
| ∂x∂y | 0 (全0矩阵) | I(单位矩阵) | A | AT |
| y | au | Au | u+v |
|---|
| ∂x∂y | a∂x∂u | A∂x∂u | ∂x∂u+∂x∂v |
⭐∂y∂<x,y>=∂xT 十分常用!
自动求导
PyTorch 通过自动计算导数,即自动求导(automatic differentiation)来加快求导,即计算一个函数在指定值上的导数,不同于符号求导、数值求导。
在实际中,根据设计的模型,系统会构建一个计算图(computational graph,将代码分解成一个个操作子,将计算表示成一个无环图),来跟踪计算是哪些数据通过哪些操作组合起来产生输出。自动求导使系统能够随后,反向传播梯度。
深度学习耗GPU资源的最大原因——由于自动求导的反向累积的内存复杂度为O(n)(需要存储正向累计的所有中间结果)
其中反向传播(backpropagation)意味着跟踪整个计算图,填充关于每个参数的偏导数,它分为两个主要过程:Forward Pass 以及 Backward Pass。
实例
假设y^=x∗ω,loss=(y^−y)2=(x⋅ω−y)2
则 Forward Pass 如下过程:(计算各点的值,局部的梯度)

通过PyTorch实现:
1 2 3
| w = torch.Tensor([1.0]) w.requires_grad = True l = loss(x, y)
|
当子节点要求计算梯度时(requires_gread = True),则父节点也会进行自动求导,求出相应的梯度(但并未存放)
Backward Pass 如下过程:(取出之前计算的中间结果,进行链式法则运算,得到损失函数关于其他变量的梯度)

只有当损失函数调用 backward(),梯度才会存放到被显式要求计算梯度的参数中,计算图也相应释放
在默认情况下,PyTorch 会累积梯度,因此在使用反向传播前需要清除之前的梯度: