Pytorch | Debug RuntimeError: one of the variables needed for gradient computation has been modified

 

实验背景:

使用pytorch训练模型过程中,我们可以通过修改模型结构尝试改进模型效果。

修改模型后,如添加了特殊的操作(op)或特殊的层结构,再训练模型时经常会遇到错误信息如下:

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [64, 64]], which is output 0 of ExpBackward, is at version 44; 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).

 

我的情况是在添加了指数计算操作exp()后,出现报错提示该op出错(is output 0 of ExpBackward),并提示该操作的梯度被其他op修改(inplace),建议设置with torch.autograd.set_detect_anomaly(True)

 

解决方案:

1. 修改op的参数 inplace=False

在搜索引擎上找到很多类似的问题,解法根据提示信息,将指定的op的inplace参数设置为False。示例代码如下:

exp = torch.exp(inplace=False)

这个解法我尝试之后没有解决问题,所以找到第2个解法。

 

2. detach() 分离变量

这个思路和inplace参数类似,将要求导的变量在操作op和op之间分离。示例代码如下:

# before
a = torch.mm(x1, x2)
a = torch.exp(a)

# after
a = torch.mm(x1, x2)
a = torch.exp(a.detach())

其中变量a是x1和x2的乘积结果,然后对它进行指数操作,在对exp传参变量a进行分离后,得到一个复制变量对其进行指数操作。

问题解决~

 

为什么detach()分离操作可以解决这个问题?下面具体看下detach()的定义:

在pytorch的官方文档里找到说明:torch.Tensor.detach

摘抄部分说明如下:

Returns a new Tensor, detached from the current graph.

The result will never require gradient.

说明detach这个操作会返回一个新的Tensor,并且该tensor不要求任何梯度的计算。所以呼应报错信息,detach确实可以解决梯度已被更新的冲突。

但我们要思考该操作是否会对整体模型的精度造成影响?

在我的case里,之所以会出现这个问题是我重复使用同一个变量a,同时记录了矩阵乘mm操作的输出,以及exp操作的输出。这是导致出现梯度冲突的根本原因。

那么我们将a tensor做了分离处理后,相当于设置了一个临时变量转存了a的值,然后再往下计算。在计算梯度的过程中不计算临时变量的梯度,但对于exp和mm操作的输出照常计算。因而该操作在当前讨论的情况下不会导致精度受损。

 

 

欢迎大家多多指正讨论!

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值