autograd
- 自动求梯度
- 概念
- tensor
- 梯度
自动求梯度
概念
在深度学习中,我们经常需要对函数求梯度(gradient)。PyTorch提供的autograd包能够根据输入和前向传播过程自动构建计算图,并执行反向传播。
其中Tensor
是这个包的核心类,如果将其属性.requires_grad
设置为True
,它将开始追踪(track)在其上的所有操作(这样就可以利用链式法则进行梯度传播了)。完成计算后,可以调用.backward()
来完成所有梯度计算。此Tensor
的梯度将累积到.grad
属性中。
注意在y.backward()
时,如果y
是标量,则不需要为backward()
传入任何参数;否则,需要传入一个与y
同形的Tensor
。
如果不想要被继续追踪,可以调用.detach()
将其从追踪记录中分离出来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了。此外,还可以用with torch.no_grad()
将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数(requires_grad=True
)的梯度。Function
是另外一个很重要的类。Tensor
和Function
互相结合就可以构建一个记录有整个计算过程的有向无环图(DAG)。每个Tensor
都有一个.grad_fn
属性,该属性即创建该Tensor
的Function
,
就是说该Tensor
是不是通过某些运算得到的,若是,则grad_fn
返回一个与这些运算相关的对象,否则是None。
tensor
// 创建一个Tensor并设置requires_grad=True:
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.grad_fn)
//输出
//tensor([[1., 1.],
// [1., 1.]], requires_grad=True)
//None
y = x + 2
print(y)
print(y.grad_fn)
//输出
//tensor([[3., 3.],
// [3., 3.]], grad_fn=<AddBackward>)
//<AddBackward object at 0x1100477b8>
注意x是直接创建的,所以它没有grad_fn, 而y是通过一个加法操作创建的,所以它有一个为 (AddBackward)的grad_fn。 像x这种直接创建的称为叶子节点,叶子节点对应的grad_fn是None。
梯度
设 y = x + 2, z = y * y * 3 , out = z.mean()
//因为out是一个标量,所以调用backward()时不需要指定求导变量:
out.backward() # 等价于 out.backward(torch.tensor(1.))
我们来看看out
关于x
的梯度 :
print(x.grad)
//输出
//tensor([[4.5000, 4.5000],
// [4.5000, 4.5000]])
我们令out
为 , 因为
所以
所以上面的输出是正确的。
数学上,如果有一个函数值和自变量都为向量的函数 , 那么 关于
的梯度就是一个雅可比矩阵(Jacobian matrix):
而torch.autograd
这个包就是用来计算一些雅克比矩阵的乘积的。例如,如果 是一个标量函数的
的梯度:
那么根据链式法则我们有 关于 的雅克比矩阵就为:
注意:grad在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。
注:
本节主要参考PyTorch官方文档