pytorch autograd 非叶子节点的梯度会保留么?

  • 只有叶子节点的梯度得到保留,中间变量的梯度默认不保留
  • 叶子节点的值在求梯度前不允许更改,以及修改的方法

只有叶子节点的梯度得到保留,中间变量的梯度默认不保留,除非使用 retain_grad() 方法
# 叶子节点
a = torch.tensor(2.0, requires_grad=True)
b = a.exp()
b.backward()
a.grad

a 是叶子节点,b 不是叶子节点,当使用 b.backward() 求导时,只有叶子节点 a 的梯度 .grad 得到保留,非叶子节点 b.grad 则没有,如果需要保留 b 的梯度,可以使用 b.retain_grad()

a = torch.tensor(2.0, requires_grad=True)
b = a.exp()
b.retain_grad()
b.backward()
b.grad

b.backward() 只能计算一次,因为执行一次 b.backward() 后,计算图的缓冲区已经被释放,再次执行将报如下错误:

RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed
叶子节点的值在求梯度前不允许更改
# a 是叶子节点
a = torch.tensor([10.,5.,2.,3.],requires_grad=True)

# 在求梯度前,叶子节点的值被修改
a[:] = 10
a.add_(10.)

loss = (a*a).mean()
loss.backward()

如上代码所示,叶子节点在反向传播前被修改,此时 a 已经不是叶子节点了,将报如下错误:

RuntimeError: leaf variable has been moved into the graph interior

如果需要在求梯度前修改,可以如下操作

一、使用 a.data.fill_() 方法
# 叶子节点 
a = torch.tensor([10.,5.,2.,3.],requires_grad=True)
# 此时叶子节点的值被修改,但仍然是 叶子节点
a.data.fill_(5)
print(a, a.is_leaf)

# 可以正常求梯度
loss = (a*a).mean()
loss.backward()
print(a.grad)
二、使用 with torch.no_grad() 代码块
# 叶子节点
a = torch.tensor([10.,5.,2.,3.],requires_grad=True)
with torch.no_grad():
    a[:] = 0
    a.add_(5.)

# 此时可以继续求梯度 
loss = (a*a).mean()
loss.backward()
print(a.grad)
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值