requires_grad
- 创建一个
Tensor
时,使用requires_grad
参数指定是否记录对其的操作,以便之后利用backward()
方法进行梯度求解 - 一个
Tensor
的requires_grad
成员保存该Tensor
是否记录操作用于计算梯度 .requires_grad_(...)
原地改变了现有张量的requires_grad
标志。如果没有指定的话,默认输入的这个标志是False
backward
- 通过运算创建的
Tensor
,会自动被赋值grad_fn
属性。该属性表示梯度函数 - 最后得到的
Tensor
执行自身的backward()
函数,此时之前参与运算并生成当前Tensor
的叶子(leaf)Tensor
将会保存其梯度在叶子Tensor
的grad
属性中。 backward()
函数接受参数,表示在特定位置求梯度值,该参数应和调用backward()
函数的Tensor
的维度相同,或者是可broadcast
的维度。默认为torch.tensor(1)
,也就是在当前梯度为标量1的位置求叶子Tensor的梯度- 默认同一个运算得到的
Tensor
仅能进行一次backward()
。再次运算得到的Tesnor
,可以再次进行backward()
- 当多个
Tensor
从相同的源Tensor
运算得到,这些运算得到的Tensor
的backwards()
方法将向源Tensor
的grad
属性中进行数值累加 - 在PyTorch中对
Tensor
元素直接赋值会产生CopySlices backward
函数,也就是说,对Tensor
元素的赋值操作也是可以反向传播的,但是有一定条件。但是这样有时候会使得依赖于其他叶子节点赋值的叶子节点出现RuntimeError: leaf variable has been moved into the graph interior的异常,即叶子节点被移到了图内部,这时需要进行调整,修正方法有两种,第一种如果我们只有确定个数的元素需要组成一个新的Tensor
,可以使用torch.cat()
函数,第二种是当我们不知道元素个数,或者元素个数太多手写cat
太累,可以在创建有依赖的叶子节点时,指定requires_grad = False
计算梯度
简单案例
现在开始进行反向传播,因为 out
是一个标量,因此 out.backward()
和 out.backward(torch.tensor(1.))
等价。
out.backward()
输出导数 d(out)/dx
print(x.grad)
输出:
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
我们的得到的是一个数取值全部为4.5
的矩阵。让我们来调用 out
张量 “”。
可以知道和
。
因此,,因而
。
所以对于前面的 backward()
而言,括号里传入的参数就是前面导数式子中,对于求取梯度值针对的特定点。默认是全1的位置。
数学过程
通常来说, torch.autograd
是计算雅可比向量积的一个“引擎”。也就是说,给定任意向量,计算乘积
。如果
恰好是一个标量函数
的导数,即
,那么根据链式法则,雅可比向量积应该是
对
的导数:
注意:行向量的也可以被视作列向量的
。
雅可比向量积的这一特性使得将外部梯度输入到具有非标量输出的模型中变得非常方便。