autograd.Variable 是包的核心类。它包装了张量,并且支持几乎所有的操作。一旦你完成了你的计算, 就可以调用 .backward() 方法
来自动计算所有的梯度。你还可以通过 .data 属性
来访问原始的张量,而关于该 variable(变量)的梯度会被累计到 .grad
上去。
通俗来讲:
Variable实质上也就是可以变化的变量,在Pytorch中的Variable就是一个存放会变化值的地理位置,里面的值会不停发生变化,就像一个装鸡蛋的篮子,里边的鸡蛋数会不断发生变化,而Pytorch中的Tensor就好比是里面的鸡蛋。
也就是说,Pytorch都是由Tensor(Tensor 是一个多维矩阵)计算的,而Tensor里面的参数都是Variable的形式。 如果用Variable计算的话,那返回的也是一个同类型的Variable。这正好就符合了反向传播,参数更新的属性。
备注:Tensor不能反向传播,Variable可以反向传播。
Variable还有一个针对自动求导实现来说非常重要的类 - Function。
Variable 和 Function 是相互联系的, 并且它们构建了一个非循环的图,编码了一个完整的计算历史信息。 每一个 variable(变量)都有一个 .grad_fn 属性
, 它引用了一个已经创建了 Variable 的 Function。
调用.backward()
方法——实现Variable 的自动求导
.backward() 方法
。.backward() 方法
时,不必指定任何参数;.backward() 方法
时,必须去指定一个 grad_output 参数
,该参数是一个匹配 shape(形状)
的张量。Variable一般的初始化方法,默认是不求梯度的。
import torch
from torch.autograd import Variable # 导入torch中Variable模块
x_tensor = torch.randn(2,3) # 创建2*3的张量矩阵
#将tensor转换成Variable
x = Variable(x_tensor)
print(x.requires_grad)
>>>
False
x = Variable(x_tensor,requires_grad=True) #Varibale 默认时不要求梯度的,如果要求梯度,需要说明
print(x)
>>>
tensor([[0.1163, 0.7213, 0.5636],
[1.1431, 0.8590, 0.7056]], requires_grad=True)
典型范例:
import torch
from torch.autograd import Variable # torch 中 Variable 模块
tensor = torch.FloatTensor([[1,2], [3,4]]) # 创建2*2的张量矩阵
print(tensor)
>>>
tensor([[1., 2.],
[3., 4.]])
variable = Variable(tensor, requires_grad=True) # 张量转为变量——自变量x
print(variable)
>>>
tensor([[1., 2.],
[3., 4.]], requires_grad=True)
# 定义变量y关于自变量x的函数关系
## Tensor情形
t_out = torch.mean(tensor*tensor) # 求解x^2项的均值,函数表达式:y = 1/n*sum(x1^2+...+xn^2)
print(t_out)
>>>
tensor(7.5000)
## Variable情形
v_out = torch.mean(variable*variable)
print(v_out)
>>>
tensor(7.5000, grad_fn=<MeanBackward0>)
# 求解梯度
# 模拟 v_out 的误差反向传递
v_out.backward() # t_out.backward()报错,由于Tensor不能反向传播,Variable可以反向传播
print(variable.grad) # 初始 Variable 的梯度
>>>
tensor([[0.5000, 1.0000],
[1.5000, 2.0000]])
#### 梯度的计算原理:
# v_out = 1/4 * sum(variable*variable) 这是计算图中的 v_out 计算步骤
# 针对于 v_out 的梯度就是, d(v_out)/d(variable) = 1/4*2*variable = variable/2
备注: 利用Variable计算时, 它在幕后一步步默默地搭建着一个庞大的系统,叫做计算图(computational graph)。 计算图的作用:是将所有的计算步骤 (节点) 都连接起来,最后进行误差反向传递的时候,一次性将所有 Variable 里面的修改幅度 (梯度) 都计算出来, 而 Tensor 就没有这个能力。
直接print(variable)
只会输出 Variable
形式的数据,在很多时候是用不了的(比如想要用 plt 画图), 所以我们要转换一下,将它转变成Tensor
形式。
Variable转变为其他形式的方法:
.data
——将Variable 形式转变为Tensor 形式.data.numpy()
——将Variable 形式转变为Numpy 形式备注:variable为存放Variable 形式的变量名
典型范例:
import torch
from torch.autograd import Variable # torch 中 Variable 模块
tensor = torch.FloatTensor([[1,2], [3,4]]) # 创建2*2的张量矩阵
variable = Variable(tensor, requires_grad=True) # 张量转为变量——自变量x
print(variable) # Variable 形式
>>>
tensor([[1., 2.],
[3., 4.]], requires_grad=True)
print(variable.data) # tensor 形式
>>>
tensor([[1., 2.],
[3., 4.]])
print(variable.data.numpy()) # numpy 形式
>>>
[[1. 2.]
[3. 4.]]
参考链接:
莫烦pytorch学习笔记(二)——变量(Variable)
pytorch学习入门 (二) Variable(变量)
(1) 变量variable是标量的形式(例如, 它包含一个元素数据),调用.backward() 方法
求梯度。
import torch
from torch.autograd import Variable
# 创建 variable(变量)
x = Variable(torch.ones(2,2), requires_grad=True)
print(x)
>>>
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
# variable(变量)的操作
y = x+2
print(y)
>>>
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
print(y.grad_fn) # y 由操作创建,所以它有 grad_fn 属性
>>>
<AddBackward0 object at 0x12b804510>
# y 的更多操作
z = y * y * 4
out = z.mean()
print("z:{}\nout:{}\n".format(z, out))
>>>
z:tensor([[36., 36.],
[36., 36.]], grad_fn=<MulBackward0>)
out:36.0
# 求梯度
out.backward()
print(x.grad) # d(out)/dx 的梯度
>>>
tensor([[10.5000, 10.5000],
[10.5000, 10.5000]])
(2) 变量variable是非标量的形式(例如, 它包含更多的元素数据),调用.backward() 方法
求梯度,必须去指定一个 grad_output 参数
,该参数是一个匹配 shape(形状)
的张量。
import torch
from torch.autograd import Variable
# 创建 variable(变量)
x = Variable(torch.rand(3), requires_grad=True)
print(x)
>>>
tensor([0.4635, 0.4550, 0.5725], requires_grad=True)
# variable(变量)的操作
y = x*2
print(y)
>>>
tensor([0.9271, 0.9100, 1.1449], grad_fn=<MulBackward0>)
while y.data.norm() < 1000:
y = y*2
print(y)
>>>
tensor([ 949.3414, 931.8120, 1172.4226], grad_fn=<MulBackward0>)
# 求梯度
gradients = torch.FloatTensor([0.1, 1.0, 0.0001]) # 设置参数gradient
y.backward( gradient=gradients )
print(x.grad)
>>>
tensor([2.0480e+02, 2.0480e+03, 2.0480e-01])