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] 取行