PyTorch 自动微分
autograd 包是 PyTorch 中所有神经网络的核心。首先让我们简要地介绍它,然后我们将会去 训练
我们的第一个神经网络。该 autograd 软件包为 Tensors 上的所有操作提供自动微分。它是一个由
运行定义的框架,这意味着以代码运行方式定义你的后向传播,并且每次迭代都可以不同。我们
从 tensor 和 gradients 来举一些例子。
1、TENSOR
torch.Tensor 是包的核心类。如果将其属性 .requires_grad 设置为 True,则会开始跟踪针对 tensor
的所有操作。完成计算后,您可以调用 .backward() 来自动计算所有梯度。该张量的梯度将累积到
.grad 属性中。
要停止 tensor 历史记录的跟踪,您可以调用 .detach(),它将其与计算历史记录分离,并防止将来
的计算被跟踪。
要停止跟踪历史记录(和使用内存),您还可以将代码块使用 with torch.no_grad(): 包装起来。在
评估模型时,这是特别有用,因为模型在训练阶段具有 requires_grad = True 的可训练参数有利于
调参,但在评估阶段我们不需要梯度。
还有一个类对于 autograd 实现非常重要那就是 Function。Tensor 和 Function 互相连接并构建一
个非循环图,它保存整个完整的计算过程的历史信息。每个张量都有一个 .grad_fn 属性保存着创
建了张量的 Function 的引用,(如果用户自己创建张量,则g rad_fn 是 None )。
如果你想计算导数,你可以调用 Tensor.backward()。如果 Tensor 是标量(即它包含一个元素数
据),则不需要指定任何参数backward(),但是如果它有更多元素,则需要指定一个gradient 参数
来指定张量的形状。
import torch
# 创建一个张量,设置 requires_grad=True 来跟踪与它相关的计算
x = torch.ones(2, 2, requires_grad=True)
print(x)
输出:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
# 针对张量做一个操作
y = x + 2
print(y)
输出:
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
y 作为操作的结果被创建,所以它有 grad_fn
print(y.grad_fn)
输出
<AddBackward0 object at 0x00000170DC8085C8>
针对 y 做更多的操作:
z = y * y * 3
out = z.mean()# 求平均值
print(z, out)
输出
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
.requires_grad_( … ) 会改变张量的 requires_grad 标记。输入的标记默认为 False ,如果没有提供相应的参数。
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 0x0000020AE937D648>
梯度:
我们现在后向传播,因为输出包含了一个标量,out.backward() 等同于
out.backward(torch.tensor(1.))
x = torch.randn(3, requires_grad=True)
print('This is x')
print('\n')
print(x)
y = x * 2
print('This is y')
print('\n')
print(y)
while y.data.norm() < 1000: # 当y的L2范数大于1000时会自动跳出 ,不满足条件时,y的元素乘2
y = y * 2
print('=====>\n')
print(y)
输出:
This is x
tensor([ 2.7645, -1.5008, -0.0843], requires_grad=True)
This is y
tensor([ 5.5289, -3.0016, -0.1685], grad_fn=<MulBackward0>)
=====>
tensor([11.0579, -6.0032, -0.3370], grad_fn=<MulBackward0>)
=====>
tensor([ 22.1157, -12.0064, -0.6740], grad_fn=<MulBackward0>)
=====>
tensor([ 44.2314, -24.0128, -1.3480], grad_fn=<MulBackward0>)
=====>
tensor([ 88.4628, -48.0255, -2.6961], grad_fn=<MulBackward0>)
=====>
tensor([176.9257, -96.0510, -5.3922], grad_fn=<MulBackward0>)
=====>
tensor([ 353.8513, -192.1021, -10.7843], grad_fn=<MulBackward0>)
=====>
tensor([ 707.7027, -384.2041, -21.5686], grad_fn=<MulBackward0>)
=====>
tensor([1415.4054, -768.4083, -43.1373], grad_fn=<MulBackward0>)
PS:在PyTorch中data.norm()是含义
首先,它对张量y每个元素进行平方,然后对它们求和,最后取平方根。 这些操作计算就是所谓的L2或欧几里德范数
# 测验
x=torch.ones(3)
print(x)
y=x.data.norm()
print(y)
输出
tensor([1., 1., 1.])
tensor(1.7321)
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
tensor([ 258.7121, 1887.7985, -405.9723], grad_fn=<MulBackward0>)
tensor([2.0480e+02, 2.0480e+03, 2.0480e-01])
from torch.autograd import Variable
import torch
x = Variable(torch.ones(2), requires_grad = True) #vairable是tensor的一个外包装
print(x)
z=4*x*x
print(z)
y=z.norm()
print(y)
y.backward() #backward()函数表示backprop(反向传播)
print(x.grad)
输出
tensor([1., 1.], requires_grad=True)
tensor([4., 4.], grad_fn=<MulBackward0>)
tensor(5.6569, grad_fn=<NormBackward0>)
tensor([5.6569, 5.6569])