本文参考了官方文档及各个大佬的博客

在神经网络模型中需要对参数求导更新,pytorch中Autograd包为张量上的所有操作提供了自动求导机制。它是一个在运行时定义(define-by-run)的框架,这意味着反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。

本文涉及:

        Tensor属性:.grad,.grad_fn, .requires_grad

        Tensor函数:.backward(),.detach(),,retain_grad()

        函数:.zero_grad()

        求梯度函数backward()的参数gradient

Autograd包中torch.Tensor类,有个 .requires_grad

x = torch.ones(2, 2, requires_grad=True)
print(x)

#输出为
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)

当一个Tensor经历过一次运算后,它就具有了.grad_fn 属性,该属性引用了创建 Tensor 自身的Function(运算,如y=x+2),当Tensor由用户直接创建(如:x=2),那么这个Tensor的 grad_fn属性 是 None

x=torch.randn(2,2,requires_grad=True)
print(x.grad_fn)  
#输出为None

y=x*x+3
print(y.grad_fn)
#输出为<AddBackward0 object at 0x000001CB6CF9B080>
 
print(y)
#输出为
#tensor([[3.4549, 3.3672],
#        [8.2812, 3.3056]], grad_fn=<AddBackward0>)

.requires_grad属性为True时,通过调用.backward()就可以自动求导,这个张量的所有梯度将会自动累加到.grad属性上,要想梯度不被累加到.grad属性上,在神经网络模型中,可以通过调用.zero_grad()将模型所有参数梯度清零。(Tensor不具有.zero_grad())。下面有2个例子

x=torch.randn(2,requires_grad=True)
y=x*x+3
out=y.mean()
out.backward()
print(x.grad)

#输出    tensor([0.0038, 1.2940])
x=torch.randn(2,requires_grad=True)
y=x*x+3
gradient=torch.tensor([0.1, 1.0], dtype=torch.float)
y.backward(gradient)
print(x.grad)


##输出为 tensor([-0.1502,  2.4981])

例子中gradient中参数的解释:

       当输入(x)是向量,输出(y)是标量时,在x上的梯度是一个向量,这时不需要gradient参数。 当输入(x)是向量,输出(y)是向量时,y在x上的梯度是一个雅可比矩阵。torch.autograd不能直接计算完整的雅可比矩阵,但是如果我们只想要雅可比向量积,只需将这个向量(gradient)作为参数传给 backward()。上面代码就是一个求雅可比向量积的例子。下面是官方文档对.backward(gradient)的具体数学解释。

pytorch tensor练习 pytorch tensor grad_pytorch tensor练习

 

 如果现在有计算y=x*x+3,z=y*y+2,out=z.mean(),调用.backward()后,只能保存叶子结点x的梯度,无法保存非叶子节点z的梯度。想要保存非叶子节点的梯度需要调用.retain_grad()函数。下面有个例子。

x=torch.randn(2,requires_grad=True)
y=x*x+3
y.retain_grad()
z=y*y+2
out=z.mean()
out.backward()
print(y.grad)

#输出为 tensor([3.8569, 3.0063])

阻止张量历史被追踪方法:

        1.调用 .detach()

        2.将代码块包装在 with torch.no_grad():

以上加有个人理解,如有错误,感谢指正