pytorch.deatch()方法的结论与代码证明。
- datach操作,相当于一个深度拷贝,操作后返回的变量和被detach的节点不属于同一个内存id,同时之后,被detach的节点的内容被修改后,返回的变量不会随之更改。
- detach操作后返回的变量默认不进行梯度计算,因此如果希望计算该叶子节点,则需要指定其梯度计算属性。
import torch
A = torch.Tensor([1, 1., 2, 3])
B = torch.Tensor([1, 1, 1, 1])
A.requires_grad_(True)
B.requires_grad_(True)
C = A + B
E = C.detach()
F = C.detach()
E.requires_grad_(True)
D = C * A * E * F
print("C, E, F:\n", C, E, F)
D.sum().backward()
print(A.grad)
print(B.grad)
# EF的不同在于E被指定了计算梯度值,当作一个可计算梯度的叶子节点;
# 如果未指定,则就是作为一个标量,对计算有贡献,但是并不需要计算梯度。
print(E.grad)
print(F.grad)
# 1 非叶子节点不存在梯度值,特征X是,每一层的权重也是叶子;
# 2 deatch前后获得的数据是同id吗?不同;而这种detach是一种深拷贝,当然它因为是torch中的行为,因此还具有其他的功能。
C = A
# 如果输出与上面的EF值相同,且不同于变换后的C值,那就表明detach操作是一种深度拷贝。任何一方的操作不会引起另一方的数值变换。
print(id(C), id(E), id(F))
print("C, E, F:\n", C, E, F)
# ----------------------------
"""
C, E, F:
tensor([2., 2., 3., 4.], grad_fn=<AddBackward0>) tensor([2., 2., 3., 4.], requires_grad=True) tensor([2., 2., 3., 4.])
tensor([ 12., 12., 45., 112.])
tensor([ 4., 4., 18., 48.])
tensor([ 4., 4., 18., 48.])
None
-----------------------------
140374691657088 140380286141312 140380286141376
C, E, F:
tensor([1., 1., 2., 3.], requires_grad=True) tensor([2., 2., 3., 4.], requires_grad=True) tensor([2., 2., 3., 4.])
"""