(九)计算图、clone 与 detach
# 项目文件:demos/detach_graph.py
import torch
x = torch.tensor([1.0, 2.0], requires_grad=True)
branch = x.square()
copied = branch.clone()
detached = branch.detach()
print("梯度联系", copied.requires_grad, detached.requires_grad)
copied.sum().backward() # clone 仍保留通向原 x 的求导路径。
print("原 x 梯度", x.grad.tolist())
detached[0] = 9
print("detach 共用数据", branch.detach().tolist())
independent = branch.detach().clone()
independent[0] = -1
print("独立副本未改原值", branch.detach().tolist())branch=x.square() 建立从 x 到平方结果的联系,branch.clone() 复制数据后仍保留这条求导联系。因此对副本求和再反向,原 x 得到梯度 [2, 4]。
branch.detach() 得到不再沿原计算图求导的张量,但数据仍与 branch 共用。将它的首项改为 9,原平方结果也变为 [9, 4]。detach().clone() 同时完成脱离计算图和独立复制,常用于保存一份不会跟着训练变化的数据快照。
每次前向都会按本次实际执行的运算建立图。backward 使用图中的中间信息后会释放已用的求导资源;下一轮再执行模型前向。日志中的损失可以保存 loss.item(),这样记录的是数值,不会把一轮轮计算图一起保留。相关机制见 PyTorch 自动微分。