admin管理员组文章数量:1590156
目录
问题描述
出现此问题的原因
解决的办法
方法一、
方法二、(这篇文章的重点)
问题描述
Trying to backward through the graph a second time, but the saved intermediate results have already been freed. Specify retain_graph=True when calling .backward() or autograd.grad() the first time.
出现此问题的原因
举例来说,假如上图所示,你的模型中包含多个组成部分,比如生成对抗网络这种的或者其它。
你的训练过程是
步骤1、根据 loss1 更新 module1
步骤2、根据loss2 更新 module2
这时,在更新过程中你的代码可能是如下这样
loss_1 = Loss1(module1(data1), Label1)
module1.zero_grad()
loss_1.backward()
optimizer1.step() # 假如这个是module1的优化器
loss_2 = Loss2(module(data2), Label2)
module2.zero_grad()
loss_2.backward()
optimizer2.step() # 假如是module2的优化器
========================================================================
Oh,shit,他竟然报错了。然后你开始上网查原因,什么backward()里面加 retain_graph=True 之类。兴致勃勃地去试了,发现没什么用。(+_+)? (←此时你的表情)。
最终你无奈的面无表情的点进了这篇文章。
========================================================================
根据翻译,知道了其中有个东西想被用了两次,但是这东西不见了。
这个被用来两次的东西就是图中的module1的梯度!!!从图中可以看到,module1经过了两次反向传播的梯度流,如红色和蓝色所示。但是在经历步骤1完成后,module1的哪个东西被释放掉了。
但你可能会问:更新module2和module1有什么关系?为什么还要用module1的那个东西呢?
问得好!(●'◡'●)这就是问题的关键所在。
从图中可以看到,module2的输入数据data2可是由module1生成的。所以,在计算loss时框生成的计算图是把module1包含在内的。这就导致module2的梯度反向传播流一直从结尾回传到开头,所以必经module1。
综上,造成了矛盾,步骤1后那个东西没了,但module2的反向传播想用。
解决的办法
方法一、
在步骤1时保留那个东西。即步骤1的
loss_1.backward( retain_graph=True)
这个有时候不行,我不知道为什么。
方法二、(这篇文章的重点)
使步骤2时的反向梯度流在module2的输入处截断,也就是在步骤2时不去使用module1的那个东西了。如图中的金色箭头所示。这种方法最妥当。步骤1理论上可以解决,但是造成了算力上的浪费。
具体操作
loss_2 = Loss2(module(data2.detach()), Label2)
在 data2后面加 detach()。截断反向传播梯度流。
========================================================================
我猜你们跑通了。然后给我点个赞(lll¬ω¬)。哈哈哈哈,我不吃牛肉
本文标签: TIMEGraphintermediatesaved
版权声明:本文标题:关于Trying to backward through the graph a second time, but the saved intermediate 的问题 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1725804250a1043817.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论