一、Variable是什么?
在torch中的Variable就是一个存放会变化的值的地理位置,里面的值会不断的变化。就像是一个装鸡蛋的篮子,里面的鸡蛋数会不停变动。就是torch里面的tensor会不断的变化,如果用Variable进行计算,那么返回的也是同一类型的Variable。
import torch
from torch.autograd import Variable
#鸡蛋
tensor=torch.FloatTensor([[1,2],[3,4]])
#将鸡蛋放进篮子,requries_grad是参与不参与误差反向传播,要不要计算梯度
variable=Variable(tensor,requires_grad=True) #variable中包含着tensor的值,variable不是tensor
print(tensor)
print(variable)
运行结果:
tensor([[1., 2.],
[3., 4.]])
tensor([[1., 2.],
[3., 4.]], requires_grad=True)
如果variable=Variable(tensor)或者将requires_grad设置为False,即不参与误差反向传播,那么运行结果variable和tensor是一样的。
二、Variable 计算,梯度
- 对比一下tensor和Variable中的计算有什么区别
#tensor和Variable的数学运算对比
t_mean=torch.mean(tensor*tensor) #tensor*tensor=tensor^2
v_mean=torch.mean(variable*variable)
print(t_mean)
print(v_mean)
运行结果:
tensor(7.5000)
tensor(7.5000, grad_fn=<MeanBackward0>)
tensor和Variable中的数学计算看不出很大的区别。但是Variable计算时,它在后面一步步默默地搭建着一个庞大的系统,叫做计算图(computational graph)。这个图是用来将所有的计算步骤(节点)都连接起来,最后进行误差反向传播的时候,一次性将所有variable里面的梯度都计算出来,而tensor就没有这种能力了。
v_mean=torch.mean(variable*variable)就是在计算图(computational graph)中添加的一个计算步骤。
- 计算梯度
#计算梯度
v_mean.backward() #模拟v_mean的误差反向传播
#Variable是计算图中的一部分,可以用来传递误差。
#前面步骤中的v_mean=torch.mean(variable*variable)就是 v_mean=1/4*sum(variable^2)
#v_mean的梯度就是:d(v_mean)/d(variable)=1/4*2*variable=1/2*variable,就是v_mean对variable求导数的过程
v_grad=variable.grad #初始Variable的梯度
print(v_grad) #初始Variable的梯度
运行结果:
tensor([[0.5000, 1.0000],
[1.5000, 2.0000]])
三、获取Variable中的数据
Variable中装着tensor数据,如果print(variable)会输出Variable形式的数据,在很多时候是用不了的(比如用matplotlib画图的时候),所以需要转化。
#获取variable中的数据
print(variable) #Variable形式
print(variable.data) #tensor形式
print(variable.data.numpy()) #numpy形式,Variable形式是无法直接转换为numpy的
运行结果:
tensor([[1., 2.],
[3., 4.]], requires_grad=True)
tensor([[1., 2.],
[3., 4.]])
[[1. 2.]
[3. 4.]]
忽略上边的梯度计算部分,如果数据不参与误差反向传播,也就是刚开始的时候variable=Variable(tensor[,requires_grad=False]),则输出的variable也是tensor数据,就可以直接使用variable.numpy(),无需variable.data.numpy。因为Variable中之后tensor数据,没设置别的属性,所以说可以这么用。
但是为了防止代码出现错误,最好还是使用variable.data.numpy()的形式。