在PyTorch中,autograd是所有神经网络的核心内容,为Tensor所有操作提供自动求导方法。
它是一个按运行方式定义的框架,这意味着backprop是由代码的运行方式定义的。
一、Variable
autograd.Variable 是autograd中最核心的类。 它包装了一个Tensor,并且几乎支持所有在其上定义的操作。一旦完成了你的运算,你可以调用 .backward()来自动计算出所有的梯度。
Variable有三个属性:data,grad以及creator。
访问原始的tensor使用属性.data; 关于这一Variable的梯度则集中于 .grad; .creator反映了创建者,标识了是否由用户使用.Variable直接创建(None)。
还有一个对autograd的实现非常重要的类——Function。Variable 和Function数是相互关联的,并建立一个非循环图,从而编码完整的计算过程。每个变量都有一个.grad_fn属性引用创建变量的函数(除了用户创建的变量,它们的grad_fn是None)。
import torch from torch.autograd import Variable
创建变量x:
x = Variable(torch.ones(2, 2), requires_grad=True) print(x)
输出结果:
Variable containing: 1 1 1 1 [torch.FloatTensor of size 2x2]
在x基础上进行运算:
y = x + 2
print(y)
输出结果:
Variable containing: 3 3 3 3 [torch.FloatTensor of size 2x2]
查看x的
grad_fn:
print(x.grad_fn)
输出结果:
None
查看y的
grad_fn:
print(y.grad_fn)
输出结果:
<torch.autograd.function.AddConstantBackward object at 0x7f603f6ab318>
可以看到y是作为运算的结果产生的,所以y有
grad_fn,而x是直接创建的,所以x没有grad_fn。
在y基础上进行运算:
z = y * y * 3 out = z.mean() print(z, out)
输出结果:
Variable containing: 27 27 27 27 [torch.FloatTensor of size 2x2] Variable containing: 27 [torch.FloatTensor of size 1]
二、Gradients
如果Variable是一个标量(例如它包含一个单元素数据),你无需对backward()指定任何参数.
out.backward()
等价于out.backward(torch.Tensor([1.0])).
out.backward() print(x.grad)
输出结果:
Variable containing: 4.5000 4.5000 4.5000 4.5000 [torch.FloatTensor of size 2x2]
如果它有更多的元素(矢量),你需要指定一个和tensor的形状匹配的grad_output参数(y在指定方向投影对x的导数)
x = torch.randn(3) x = Variable(x, requires_grad=True) y = x * 2 while y.data.norm() < 1000: y = y * 2 print(y)
输出结果:
Variable containing: -1296.5227 499.0783 778.8971 [torch.FloatTensor of size 3]
不传入参数:
y.backward() print(x.grad)
输出结果:
RuntimeError: grad can be implicitly created only for scalar outputs None
传入参数:
gradients = torch.FloatTensor([0.1, 1.0, 0.0001]) y.backward(gradients) print(x.grad)
输出结果:
Variable containing: 102.4000 1024.0000 0.1024 [torch.FloatTensor of size 3]
简单测试一下不同参数的效果:
参数1:[1,1,1]
x=torch.FloatTensor([1,2,3]) x = Variable(x, requires_grad=True) y = x * x print(y) gradients = torch.FloatTensor([1,1,1]) y.backward(gradients) print(x.grad)
输出结果:
Variable containing: 1 4 9 [torch.FloatTensor of size 3] Variable containing: 2 4 6 [torch.FloatTensor of size 3]
参数2:[3,2,1]
x=torch.FloatTensor([1,2,3]) x = Variable(x, requires_grad=True) y = x * x print(y) gradients = torch.FloatTensor([3,2,1]) y.backward(gradients) print(x.grad)
输出结果:
Variable containing: 1 4 9 [torch.FloatTensor of size 3] Variable containing: 6 8 6 [torch.FloatTensor of size 3]