【backward解决方案与原理】网络模型在梯度更新时出现变量版本号机制错误

编程入门 行业动态 更新时间:2024-10-28 18:23:20

【backward解决方案与原理】网络模型在<a href=https://www.elefans.com/category/jswz/34/1767879.html style=梯度更新时出现变量版本号机制错误"/>

【backward解决方案与原理】网络模型在梯度更新时出现变量版本号机制错误

【backward解决方案与原理】网络模型在梯度更新时出现变量版本号机制错误

  • 报错详情
  • 错误产生背景
  • 原理
  • 解决方案

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation

报错详情

  模型在backward时,发现如下报错:

  即RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation

  其大概意思是说,当在计算梯度时,某个变量已经被操作修改了,这会导致随后的计算梯度的过程中该变量的值发生变化,从而导致计算梯度出现问题。

错误产生背景

  起因是我要复现一种层级多标签分类的网络结构:

  当输入序列 x x x经过一次BERT模型之后,得到当前预测的一级标签,然后拼接到输入序列 x x x上,再次输入到BERT模型里以预测二级标签。

  出错版本的模型结构如下:

def forward(self, x, label_A_emb):context = x[0]  # 输入的句子mask = x[2]  d1 = self.bert(context, attention_mask=mask)logit1 = self.fc1(d1[1])  # [batch_size, label_A_num] = [128, 34]idx = torch.max(logit1.data, 1)[1] # [batch_size] = [128]extra = label_A_emb[idx]context[:, -3:] = extramask[:, -3:] = 1d2 = self.bert(context, attention_mask=mask)logit2 = self.fc2(d2[1])  # [batch_size, label_B_num] = [128, 34]return logit1, logit2

  在计算梯度时,由于contextmask的值被中间修改过一次,所以会报错。

原理


  图中 w 1 w_1 w1​的梯度计算如上图,损失函数为 E t o t a l E_{total} Etotal​,最终 w 1 w_1 w1​的梯度里是需要用到原始输入 i 1 i_1 i1​的。

  所以在上面贴的模型结构代码中,输入在经过神经网络之后,又作了一次改动,然后再经过神经网络。但是梯度计算会计算两次的梯度,可是发现输入只有改动后的值了,改动前的值已经被覆盖。

计算梯度时的版本号机制是PyTorch中用于跟踪张量操作历史的一种机制。它允许PyTorch在需要计算梯度时有效地管理和跟踪相关的操作,以便进行自动微分。每个张量都有一个版本号,记录了该张量的操作历史。当对一个张量执行就地操作(inplace operation)时,例如修改张量的值或重新排列元素的顺序,版本号会增加。这种就地操作可能导致计算梯度时出现问题,因为梯度计算依赖于操作历史。

解决方案

  把即将改动的变量深拷贝一份,最终优化的代码如下:

def forward(self, x, label_A_emb):context = x[0]  # 输入的句子mask = x[2]  d1 = self.bert(context, attention_mask=mask)logit1 = self.fc1(d1[1])  # [batch_size, label_A_num] = [128, 34]idx = torch.max(logit1.data, 1)[1] # [batch_size] = [128]extra = label_A_emb[idx]context_B = copy.deepcopy(context)mask_B = copy.deepcopy(mask)context_B[:, -3:] = extramask_B[:, -3:] = 1d2 = self.bert_A(context_B, attention_mask=mask_B)logit2 = self.fc2(d2[1])  # [batch_size, label_B_num] = [128, 34]return logit1, logit2

更多推荐

【backward解决方案与原理】网络模型在梯度更新时出现变量版本号机制错误

本文发布于:2023-11-16 14:14:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1625017.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:梯度   变量   版本号   模型   原理

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!