Pytorch中的.backward()方法

2021-04-16 16:47:17 浏览数 (1)

PyTorch的主要功能和特点之一就是backword函数,我知道一些基本的导数:

代码语言:javascript复制
Let, F = a*b
Where,
a = 10 
b = 10∂F/∂a = b => ∂F/∂a = 20
∂F/∂b = a => ∂F/∂b = 10

让我们在PyTorch中实现:

如果a和b是向量,那么下面的代码似乎给出了一个错误:

代码语言:javascript复制
RuntimeError: grad can be implicitly created only for scalar outputs

在文档中写道:当我们调用张量的反向函数时,如果张量是非标量(即它的数据有不止一个元素)并且要求梯度,那么这个函数还需要指定特定梯度。

这里F是非标量张量所以我们需要把梯度参数传递给和张量F维数相同的反向传播函数

在上面的代码示例中,将梯度参数传递给backword函数并给出了所需的梯度值a和b。但是,为什么我们必须将梯度参数传递给backword函数?

要理解这一点,我们需要了解.backward()函数是如何工作的。再次提到这些文档:

torch.autograd是一个计算向量-雅可比积的引擎。即给定任意向量v,计算其乘积J@v.T注:@表示矩阵乘法

一般来说,雅可比矩阵是一个全偏导数的矩阵。如果我们考虑函数y它有n维的输入向量x它有m维的输出。然后计算包含以J表示的所有偏导数的雅可比矩阵:

v为backword函数提供的外梯度。另外,需要注意的另一件重要的事情是,默认情况下F.backward()与F.backward(gradient=torch.tensor([1.])相同,所以默认情况下,当输出张量是标量时,我们不需要传递梯度参数,就像我们在第一个例子中所做的那样。

当输出张量为标量时,则v_vector的大小为1,即torch.tensor([1.]),可以用值1代替。这样就得到了完整的雅可比矩阵,也就是J@v。T = J

但是,当输出张量是非标量时,我们需要传递外部梯度向量v,得到的梯度计算雅可比向量积,即J@v.T

在这里,对于F = a*b在a = [10.0, 10.0] b =[20.0, 20.0]和v =[1]。1。我们得到∂F/∂a :

到目前为止,我们有:

我们引入一个新的变量G,它依赖于F

到目前为止都很好,但是让我们检查一下F的grad值也就是F.grad

我们得到None,并显示了一个警告

代码语言:javascript复制
The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the gradient for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor......

在前向传播过程中,自动动态生成计算图。对于上面的代码示例,动态图如下:

从上面的计算图中,我们发现张量A和B是叶节点。我们可以用is_leaf来验证:

Torch backward()仅在默认情况下累积叶子节点张量的梯度。因此,F grad没有值,因为F张量不是叶子节点张量。为了积累非叶子节点的梯度,我们可以使用retain_grad方法如下:

在一般的情况下,我们的损失值张量是一个标量值,我们的权值参数是计算图的叶子节点,所以我们不会得出上面讨论的误差条件。但是了解这些特殊的情况,这有助于了解更多关于pytorch的功能,万一那天用上了呢,对吧。

作者:Abishek Bashyal

原文地址:https://anishbashyal10.medium.com/playing-with-backward-method-in-pytorch-bd34b58745a0

deephub翻译组

0 人点赞