0%

Pytorch中的autograd

Pytorch中的autograd

  • 在整个Pytorch框架中,所有的神经网络本质上都是一个autograd packge(自动求导工具包)
  • autograd package 提供了一个对Tensors上所有的操作进行自动微分的功能

关于torch.Tensor

  • torch.Tensor是整个package中的核心类,如果将属性.requires_grad这设备为True,它将追踪在这个类上定义的所有操作。当代码要进行反向传播时,直接调用.backward()就可以自动计算所有的梯度。在这个Tensor上的所有梯度将被累加进属性.grad
  • 如果想终止一个Tensor在计算图中的追踪回溯,只需要执行.detach()就可以将该Tensor从计算图中撤下,在未来的回溯计算中也不会再计算该Tensor
  • 除了.detach(),如果想终止对计算图的回溯,也就是不再进行方向传播求导数的过程,也可以采用代码块的方式with torch.no_grad():,这种方式非常适用于对模型进行预测的时候,因为预测阶段不再需要对梯度进行计算

关于torch.Function

  • Function类是和Tensor类同等重要的一个核心类,它和Tensor共同构建了一个完整的类,每个Tensor拥有一个.grad_fn属性,代表引用了哪个具体的Function创建了该Tensor
  • 如果某个张量Tensor是用户自定义的,则其对应的grad_fn是None

关于Tensor的操作

1
2
3
4
x1 = torch.ones(3, 3)
print(x1)
x = torch.ones(2, 2, requires_grad=True)
print(x)

tensor([[1., 1., 1.],

​ [1., 1., 1.],

​ [1., 1., 1.]])

tensor([[1., 1.],

​ [1., 1.]], requires_grad=True)

在具有requires_grad=True上的Tensor上执行一个加法操作

1
2
y = x + 2
print(y)

tensor([[3., 3.],

​ [3., 3.]], grad_fn=)

打印Tensor的grad_fn属性

1
2
print(x.grad_fn)
print(y.grad_fn)

None

<AddBackward0 object at 0x7f57cf678090>

在Tensor上执行更复杂的操作

1
2
3
z = y*y*3
out = z.mean()
print(z, out)

tensor([[27., 27.],

​ [27., 27.]], grad_fn=) tensor(27., grad_fn=)

使用.requires_grad_()

.requires_grad()可以原地改变Tensor的属性.requires_grad的值,如果没有主动设定,默认是False

1
2
3
4
5
6
7
a = torch.randn(2, 2)
a = ((a*3)/(a-1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a*a).sum()
print(b.grad_fn)

False

True

<SumBackward0 object at 0x7f57cf5d66d0>

关于梯度Gradients

在Pytorch中,反向传播是依靠.backward()实现的

1
2
out.backward()
print(x.grad)

tensor([[4.5000, 4.5000],

​ [4.5000, 4.5000]])

关于自动求导

关于自动求导的属性设置,可以通过设置.require_grad=True来执行自动求导,也可以通过代码块的限制来停止自动求导

1
2
3
4
print(x.requires_grad)
print((x**2).requires_grad)
with torch.no_grad():
print((x**2).requires_grad)

True

True

False

可以通过.detach()获得一个新的Tensor,拥有相同的内容但不会自动求导

1
2
3
4
print(x.requires_grad)
y = x.detach()
print(y.requires_grad)
print(x.eq(y).all())

True

False

tensor(True)