detach就是把网络中的一部分分量从反向传播的流程中拿出来,使之requires_grad=False
但是拿出来的时候,还是指向原向量的地址,所以对拿出来的向量进行操作的时候,也会影响原向量。
注意:使用detach返回的tensor和原始的tensor共同一个内存,即一个修改另一个也会跟着改变。
当使用detach()分离tensor但是没有更改这个tensor时,并不会影响backward()。
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进行更改,所以并不会影响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.1966, 0.1050, 0.0452])
'''
二、 tensor.detach_()
将一个tensor从创建它的图中分离,并把它设置成叶子tensor。
其实就相当于变量之间的关系本来是x -> m -> y,这里的叶子tensor是x。但是这个时候对m进行了m.detach_()操作,其实就是进行了两个操作:
(1)将m的grad_fn的值设置为None,这样m就不会再与前一个节点x关联,这里的关系就会变成x, m -> y,此时的m就变成了叶子结点;
(2)然后会将m的requires_grad设置为False,这样对y进行backward()时就不会求m的梯度》
总结:其实detach()和detach_()很像,两个的区别就是detach_()是对本身的更改【原地操作】,detach()则是生成了一个新的tensor。
比如x -> m -> y中如果对m进行detach(),后面如果反悔想还是对原来的计算图进行操作还是可以的。
但是如果是进行了detach_(),那么原来的计算图也发生了变化,就不能反悔了。
仅供自己学习使用,如有侵权,请联系。