PyTorch双分支网络训练时loss.backward()触发inplace操作报错如何解决
问题定位
从你开启异常检测后的报错栈可以直接定位到问题根源:你网络中/module/blocks.py文件第228行使用的ReLU层启用了inplace=True参数,进行了就地修改操作。
你当前用的是残差结构out = self.relu(a + b),且是双输入双输出的分支网络,这个ReLU的输入(a+b的结果)以及输出会被多个计算分支复用,inplace操作会直接修改张量的原始值,导致反向传播计算梯度时找不到最初的张量值,就出现了「版本2期望版本1」的报错。
解决步骤
- 优先修改对应ReLU的配置:找到
blocks.py中定义self.relu的代码行,将nn.ReLU(inplace=True)修改为nn.ReLU(inplace=False),即可解决绝大多数此类问题。 - 若修改后仍报错,进一步排查所有可能的inplace操作:
- 检查全网络所有激活层(ReLU、LeakyReLU、Silu等)的
inplace参数,分支共享特征的场景下建议全部设为False - 排查代码中是否存在
x += y、x *= 系数这类就地修改张量的操作,将其改为x = x + y、x = x * 系数的非就地写法 - 你提供的损失函数、训练循环代码均无inplace修改操作,不需要调整
- 检查全网络所有激活层(ReLU、LeakyReLU、Silu等)的
- 验证修改效果:修改完成后可先关闭
set_detect_anomaly直接运行,若仍报错再开启异常检测定位新的问题点。
可选调试手段
如果仍无法定位,可在模型前向传播时将报错提到的[2,256,16,16]形状的张量(即istage4的输出a4)保存下来,在loss.backward()调用前打印a4._version的值,对比前向传播结束时的版本号,哪一步之后版本号加1,就说明那一步做了inplace修改。
内容的提问来源于stack exchange,提问作者tachyon
相关产品推荐
相关产品推荐

