Pytorch Bug解决:RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
编程环境
Python:3.9
Pytorch:1.11.0
Bug描述
Traceback (most recent call last):
File "E:\Anaconda\envs\torch_c_13\lib\site-packages\IPython\core\interactiveshell.py", line 3343, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-18bbaf295f9c>", line 1, in <module>
runfile('E:/Code/AEs by PyTorch/AEsingle_train_test_temp.py', wdir='E:/Code/AEs by PyTorch')
File "E:\SoftWare\PyCharm\PyCharm 2021.2.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "E:\SoftWare\PyCharm\PyCharm 2021.2.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "E:/Code/AEs by PyTorch/AEsingle_train_test_temp.py", line 205, in <module>
train_ae_x_h2 = AEtrain(AEmodel2, train_ae_x_h1, 10, "AEmodel2")
File "E:/Code/AEs by PyTorch/AEsingle_train_test_temp.py", line 95, in AEtrain
loss.backward()
File "E:\Anaconda\envs\torch_c_13\lib\site-packages\torch\tensor.py", line 195, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "E:\Anaconda\envs\torch_c_13\lib\site-packages\torch\autograd\__init__.py", line 99, in backward
allow_unreachable=True) # allow_unreachable flag
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [784, 512]], which is output 0 of TBackward, is at version 3; expected version 2 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
梯度计算所需的变量之一已被 inplace 操作修改。
bug分析
查看报错信息发现是loss.backward()部分报错,即在根据损失计算某个变量反向传播的梯度时,该变量被inplace操作修改了,即被原地修改,而不是将变化后的值赋给一个新的变量(类似于 a += 1 的操作)。因为反向传播遵循的是链式求导法则,这种原地修改的操作有时会使得模型计算梯度时找不到依赖的变量,从而导致梯度信息丢失或恶意篡改。
解决方法
- 找到网络模型中的 inplace 操作,将inplace=True改成 inplace=False,例如torch.nn.ReLU(inplace=False)
- 将代码中的“a+=b”之类的操作改为“c = a + b”
- 将loss.backward()函数内的参数retain_graph值设置为True, loss.backward(retain_graph=True),如果retain_graph设置为False,计算过程中的中间变量使用完即被释放掉。
注意:所以大家在平常写代码的时候一定要养成良好的习惯,不乱用变量,注意代码的简洁性和高效性。