pytorch basic(二)detach&contiguous&切片

文章详细介绍了PyTorch中tensor.detach()函数的用途,它用于从计算图中分离一个张量,使其不再保留梯度信息,常用于在网络训练中阻止某些变量的更新。同时,文章通过示例展示了detach()的正确和错误用法,以及detach_()和contiguous()函数的区别和应用场景。
摘要由CSDN通过智能技术生成

tensor.detach()

返回一个新的tensor,从当前计算图中分离下来的,但是仍指向原变量的存放位置(当一个被修改,另一个也会修改),不同之处只是requires_grad为false,得到的这个tensor永远不需要计算其梯度,不具有grad。即使之后重新将它的requires_grad置为true,它也不会具有梯度grad

即在网络训练过程中希望某些变量的参数不保持更新,切断一些分支的反向传播。

正常使用例:
import torch
 
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
 
out.sum().backward()
print(a.grad)
'''
None 还未反向传播,没计算梯度
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward>)
tensor([0.1966, 0.1050, 0.0452])  反向传播计算梯度
'''

 
#添加detach(),c的requires_grad为False
c = out.detach()
print(c)
 
#这时候没有对c进行更改,所以并不会影响backward()
out.sum().backward()
print(a.grad)
 
'''返回:
tensor([0.7311, 0.8808, 0.9526])
tensor([0.1966, 0.1050, 0.0452])
'''

错误情况 

1. 用detach返回的值进行求导

2.更改了detach返回值,因为同样修改了原本值,会报错 

import torch
 
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
 
#添加detach(),c的requires_grad为False
c = out.detach()
print(c)
 
#使用新生成的Variable进行反向传播
c.sum().backward()
print(a.grad)
 
'''返回:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward>)
tensor([0.7311, 0.8808, 0.9526])
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    c.sum().backward()
  File "/anaconda3/envs/deeplearning/lib/python3.6/site-packages/torch/tensor.py", line 102, in backward
    torch.autograd.backward(self, gradient, retain_graph, create_graph)
  File "/anaconda3/envs/deeplearning/lib/python3.6/site-packages/torch/autograd/__init__.py", line 90, in backward
    allow_unreachable=True)  # allow_unreachable flag
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
'''


import torch
 
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
 
#添加detach(),c的requires_grad为False
c = out.detach()
print(c)
c.zero_() #使用in place函数对其进行修改
 
#会发现c的修改同时会影响out的值
print(c)
print(out)
 
#这时候对c进行更改,所以会影响backward(),这时候就不能进行backward(),会报错
out.sum().backward()
print(a.grad)
 
'''返回:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward>)
tensor([0.7311, 0.8808, 0.9526])
tensor([0., 0., 0.])
tensor([0., 0., 0.], grad_fn=<SigmoidBackward>)
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    out.sum().backward()
  File "/anaconda3/envs/deeplearning/lib/python3.6/site-packages/torch/tensor.py", line 102, in backward
    torch.autograd.backward(self, gradient, retain_graph, create_graph)
  File "/anaconda3/envs/deeplearning/lib/python3.6/site-packages/torch/autograd/__init__.py", line 90, in backward
    allow_unreachable=True)  # allow_unreachable flag
RuntimeError: one of the variables needed for gradient computation has been modified 
by an inplace operation
'''

torch.detach_()

将一个tensor从创建它的图中分离,并把它设置成叶子tensor

计算图:x -> m -> y 用m.detach(),相当于返回一个新值,不影响计算图。

当用m.detach_(),此时m的grad_fn的值设置为None,这样m就不会再与前一个节点x关联,这里的关系就会变成x, m -> y,此时的m就变成了叶子结点,然后会将m的requires_grad设置为False,这样对y进行backward()时就不会求m的梯度!

tensor.contiguous()

x是一个Tensor,x.contiguous()的作用就是返回一个在内存中连续的Tensor,其data与Tensor x一致。如果源x本来就在内存中连续的话,那就返回其本身。

在pytorch中,诸如以下操作:

narrow()view()expand()transpose()permute()

 只会改变tensor x的读取顺序,但不会改变x的实际内存顺序。因此需要添加contiguous来重新生成一个读取顺序与内存数据相符的新tensor。

通常只需在报错:RuntimeError: input is not contiguous时添加contiguous即可。

关于切片:

# for 2-D Matrix

import torch
x = torch.arange(12).reshape(3,4)
# tensor([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])


ind1 = torch.tensor([0, 2, 1])
ind2 = torch.tensor([True, False, True])
ind3 = torch.tensor([0, 1])

x[ind1]
#tensor([[ 0,  1,  2,  3],
#        [ 8,  9, 10, 11],
#        [ 4,  5,  6,  7]])

x[ind2]
# tensor([[ 0,  1,  2,  3],
#         [ 8,  9, 10, 11]])
# 当索引序列为bool值时,为False不会选择该行

x[ind3]
#    tensor([[0, 1, 2, 3],
#            [4, 5, 6, 7]])

# 以上三种方式均等价于x[0],x[2],x[1] 取行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值