0.前言
最近在用Pytorch训练网络的时候出现了一个奇怪的错误,找了很久在偶然间试出了解决方法,因此记录一下,以作备忘。但具体原理还不是很清楚,也请各位大佬指教。
1.错误
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [19, 24, 30]], which is output 0 of SoftmaxBackward, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
2.查找错误
根据报错的提示显示出错的是模型反向传播的时候,即:
(policy_loss - dist_entropy * self.args.entropy_coef).backward()
但dist_entropy
和self.args.entropy_coef
都没有梯度,所以问题应该是在policy_loss
的梯度计算上,但检查了一下前向过程也并没有发现什么问题,于是按照错误提示加上了with torch.autograd.set_detect_anomaly(True)
这句,对于简单模型这句很容易加在模型开头,但我的模型稍微复杂一些,而且似乎到底放在哪也没有比较确定的说法,于是我将此句放在了模型更新的一开始,之后重新运行,在报错中出现了一个写在模型中的语句,也就是这句:
output = torch.cat(s_actions, dim=-2)
action_prob = torch.nn.functional.softmax(output, dim=-1).cpu()
看来错误应该就是出于这个地方了,这也和报错的SoftmaxBackward一致。
3.解决方法
找到了问题出处,下面就该解决了。查了一下似乎也没有我这种出现在SoftmaxBackward上的,查到的解决办法大致如下:
1.将relu
的inplace=True
改成False,但我的所有网络模块中的relu
函数都没有将inplace置为True,故此方法行不通;
2.还有是说由于模型中出现了类似+=
这样的操作,但在我仔细检查代码后,确定没有写这种,所以也只能放弃;
3.将Pytorch版本降级,其实这个确实是可以,我在服务器上的Pytorch1.4.0环境下,就没有出现这个错误,但是在本地Window环境下的Pytorch1.5.0版本环境就会出现这个错误,所以可能是和Pytorch版本有关?
4.但总是用低版本的也不是办法,于是在一通瞎试之后偶然发现,在softmax后面加上.clone()
后这个错误就神奇的消失了。最终将代码改为;
output = torch.cat(s_actions, dim=-2)
action_prob = torch.nn.functional.softmax(output, dim=-1).cpu().clone()
改完之后代码就可以运行了,具体原理还不是很清楚,希望有大神指教。