浅谈Pytorch中的Variable的使用方法

Variable的基本概念

autograd.Variable 是包的核心类。它包装了张量,并且支持几乎所有的操作。一旦你完成了你的计算, 就可以调用 .backward() 方法自动计算所有的梯度。你还可以通过 .data 属性访问原始的张量,而关于该 variable(变量)的梯度会被累计到 .grad上去。

通俗来讲:
Variable实质上也就是可以变化的变量,在Pytorch中的Variable就是一个存放会变化值的地理位置,里面的值会不停发生变化,就像一个装鸡蛋的篮子,里边的鸡蛋数会不断发生变化,而Pytorch中的Tensor就好比是里面的鸡蛋。

也就是说,Pytorch都是由Tensor(Tensor 是一个多维矩阵)计算的,而Tensor里面的参数都是Variable的形式。 如果用Variable计算的话,那返回的也是一个同类型的Variable。这正好就符合了反向传播,参数更新的属性。

备注:Tensor不能反向传播,Variable可以反向传播。

Variable的自动求导

Variable还有一个针对自动求导实现来说非常重要的类 - Function。

Variable 和 Function 是相互联系的, 并且它们构建了一个非循环的图,编码了一个完整的计算历史信息。 每一个 variable(变量)都有一个 .grad_fn 属性, 它引用了一个已经创建了 Variable 的 Function。

调用.backward() 方法——实现Variable 的自动求导

  • 计算变量variable的导数,可以在 Variable 上调用.backward() 方法
  • 如果变量variable是标量的形式(例如, 它包含一个元素数据), 则再调用.backward() 方法时,不必指定任何参数;
  • 但是, 如果变量variable是非标量的形式例如, 它包含更多的元素数据),则再调用.backward() 方法时,必须去指定一个 grad_output 参数,该参数是一个匹配 shape(形状)的张量。

PyTorch中Variable的使用方法

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 就没有这个能力。

获取Variable里面的数据

直接print(variable)只会输出 Variable 形式的数据,在很多时候是用不了的(比如想要用 plt 画图), 所以我们要转换一下,将它转变成Tensor形式。

Variable转变为其他形式的方法:

  • variable.data——将Variable 形式转变为Tensor 形式
  • variable.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])

猜你喜欢

转载自blog.csdn.net/weixin_42782150/article/details/106854349