Variable类型和自动微分模块

        Variable是PyTorch中的另一个变量类型。一旦张量被转换成Variable类型便可以实现自动求导。

Variable对象和Tensor对象之间的转换

>>> import torch
>>> from torch.autograd import Variable

>>> a = torch.FloatTensor([4])
>>> print(Variable(a))  # 将张量转换成Variable对象
tensor([4.])

>>> print(Variable(a,requires_grad=True))  # 将张量转换成支持梯度计算的Variable对象
tensor([4.], requires_grad=True) 

>>> a.data
tensor([4.])

# 在使用requires_grad时,必须要求张量的值是浮点型,pytorch不支持对整数类型进行梯度运算。

控制梯度计算的方法

torch.no_grad()

# no_grad()会使其作用域中的Variable()对象的requires_grad属性失效
# 用no_grad()函数配合with语句限制requires_grad属性的作用域
x = torch.ones(2,2,requires_grad=True)  

# tensor.ones()是一个相对上层的函数,支持requires_grad参数,该函数可以直接生成
# Variable对象,使用torch.tensor也可以支持参数设置,但是torch.Tensor()不支持参数设置

with torch.no_grad():
    y=x*2
print(y.requires_grad)  # 输出为False

# 使用函数装饰器限制requires_grad()函数的作用域
@torch.no_grad()
def doubles(x):
    return x * 2
z = doubles(x)
print(z.requires_grad)  # 输出:False

函数enable_grad()和no_grad()的嵌套

# 在函数torch.enable_grad()作用域中使用with限制requires_grad的作用域
import torch
x = torch.ones(2,2,requires_grad=True)
with torch.no_grad():  # 梯度计算属性失效
    with torch.enable_grad():  # 梯度计算属性生效
        y = x * 2
print(y.requires_grad)  # 输出:True

#################################################################
# 同样torch.enable_grad()也可以使用装饰器进行修饰
# 当torch.enable_grad()作用在没有requires_grad属性的Variable对象时,将会失效

用set_grad_enable()函数统一管理梯度计算

# 很多时候并不是调用enable_grad()和no_grad()来控制梯度计算,而是调用set_grad_enabled()函数对
# 梯度计算进行统一管理。

torch.set_grad_enabled(False)

Variable对象的属性

# grad_fn和is_leaf属性分别表示计算图中的节点和叶子节点属性
# 如果Variable对象不是通过计算生成的,那么grad_fn属性为None,is_leaf属性为True,反之亦然
>>> x = torch.tensor([1.,2.,3.],requires_grad=True)
>>> x.grad_fn
>>> print(x.grad_fn)
None
>>> x.is_leaf
True
>>> m=x+1
>>> print(m.grad_fn)
<AddBackward0 object at 0x7fbaab616e20>
>>> print(m.is_leaf)
False

# pytorch通过backward()方法实现了自动求导的功能
# 当带有需求梯度计算的张量经过一系列计算最终生成一个标量,便可以使用该标量的backward()方法进行
# 自动求导,一定要在当前变量内容时标量的情况下使用,否则会报错
>>> f=m.mean()
>>> f.backward()
>>> print(f)
tensor(3., grad_fn=<MeanBackward0>)
>>> print(x.grad)
tensor([0.3333, 0.3333, 0.3333])

>>> f=m.sum()
>>> f.backward()
>>> f
tensor(9., grad_fn=<SumBackward0>)
>>> x.grad
tensor([1.3333, 1.3333, 1.3333])

# 使用detach()方法将Variable对象分离成叶子节点
# 对张量取值时,需要求梯度的Variable对象无法直接被转换为Numpy对象,可以利用detach()方法将
# Variable对象分离成叶子节点
>>> from torch.autograd import Variable
>>> x = Variable(torch.ones(2,2),requires_grad=True)
>>> x.numpy
<built-in method numpy of Tensor object at 0x7fbb0cc42580>
>>> x.numpy()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.

# 该方法会将Variable对象从创建它的graph中分离出来,之后在进行Numpy对象的转换
>>> x.detach().numpy()
array([[1., 1.],
       [1., 1.]], dtype=float32)
# 该代码会返回一个从当前计算图中分离出的Variable对象,并使他成为叶子节点


# 实际应用中,还可以使用detach()方法来计算指定模型中参数的梯度
# 例如:模型A和B,若只计算B中参数的梯度,不想计算A中模型参数的梯度,可以用detach()方法来处理
y = A(x)
z = B(y.detach())
z.backward()

y = A(x)
y.detach_()
z = B(y)
z.backward()

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hithithithithit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值