Variable和Tensor本质上没有区别,不过Variable会被放入一个计算图中,然后进行前向传播,反向传播,自动求导。首先Variable是在torch.autograd.Variable中,要将一个tensor变成Variable也非常简单,比如想让一个tensor a变成Variable,只需要Variable(a)就可以了。Variable有三个比较重要的组成属性:data、grad和grad_fn。通过data可以取出Variable里面的tensor数值,grad_fn表示的是得到这个Variable的操作,比如通过加减还是乘除得到,最后grad是这个Variable的反向传播梯度,下面通过例子来具体说明一下。
# Creat Variable
x = Variable(torch.Tensor([1]), required_grad=True)
w = Variable(torch.Tensor([2]), required_grad=True)
b = Variable(torch.Tensor([3]), required_grad=True)
# Build a computational graph.
y = w * x * b # y = 2 * x + 3
# Compute gradient
y.backward() # same as y.backward(torch.FloatTensor([i]))
# Print out the gradient.
print(x.grad) # x.grad = 2
print(w.grad) # x.grad = 1
print(b.grad) # x.grad = 1
构建Variable,要注意得传入一个参数required_grad=True,这个参数表示是否对这个变量求梯度,默认的是False,也就是不对这个变量求梯度,这里我们希望得到这些变量的梯度,所以需要传入这个参数。从上面的代码中,我们注意到一行y.backward(),这行代码就是所谓的自动求导,这其实等价于y.backward(torch.FloatTensor([i])),只不过对于标量求导里面的参数就可以不写了,自动求导不需要你再去明确地写明对哪个函数求导,直接通过这行代码就能对所有的需要梯度的变量进行求导,得到它们的梯度,然后通过x.grad可以得到x的梯度。
上面是标量求导,同时也可以做矩阵求导,比如:
x = torch.randn(3)
x = Variable(x, required_grad=True)
y = x * 2
print(y)
y.backward(torch.FloatTensor([1, 0.1, 0.01]))
print(x.grad)
相当于给出了一个三维向量去做运算,这时候得到的结果y就是一个向量,这里对这个向量求导就不能直接写成y.backward(),这样程序是会报错的。这个时候需要传入参数声明,比如y.backward(torch.FloatTensor([1, 1, 1])),这样得到的结果就是它们每个分量的梯度,或者可以传入y.backward(torch.FloatTensor[1, 0.1, 0.01]),这样得到的梯度就是它们原本的梯度分别乘上1,0.1和1。